Dillo v3.2.0-88-g47ab7c70
Loading...
Searching...
No Matches
fltkplatform.cc
Go to the documentation of this file.
1/*
2 * Dillo Widget
3 *
4 * Copyright 2005-2007 Sebastian Geerken <sgeerken@dillo.org>
5 * Copyright 2025 Rodrigo Arias Mallo <rodarima@gmail.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include <stdio.h>
22
23#include "dlib/dlib.h"
24#include "../lout/msg.h"
25#include "../lout/debug.hh"
26#include "fltkcore.hh"
27
28#include <FL/fl_draw.H>
29#include <FL/Fl_Box.H>
30#include <FL/Fl_Tooltip.H>
31#include <FL/Fl_Menu_Window.H>
32#include <FL/Fl_Paged_Device.H>
33
34/*
35 * Local data
36 */
37
38/* Tooltips */
39static Fl_Menu_Window *tt_window = NULL;
40static int in_tooltip = 0, req_tooltip = 0;
41
42namespace dw {
43namespace fltk {
44
45using namespace lout;
46
52 FltkFont> *FltkFont::fontsTable =
54 FltkFont> (false, false);
55
57 FltkFont::FontFamily> *FltkFont::systemFonts =
58 NULL;
59
60FltkFont::FontFamily FltkFont::standardFontFamily (FL_HELVETICA,
61 FL_HELVETICA_BOLD,
62 FL_HELVETICA_ITALIC,
63 FL_HELVETICA_BOLD_ITALIC);
64
65FltkFont::FontFamily::FontFamily (Fl_Font fontNormal, Fl_Font fontBold,
66 Fl_Font fontItalic, Fl_Font fontBoldItalic)
67{
68 font[0] = fontNormal;
69 font[1] = fontBold;
70 font[2] = fontItalic;
71 font[3] = fontBoldItalic;
72}
73
74void FltkFont::FontFamily::set (Fl_Font f, int attrs)
75{
76 int idx = 0;
77 if (attrs & FL_BOLD)
78 idx += 1;
79 if (attrs & FL_ITALIC)
80 idx += 2;
81 font[idx] = f;
82}
83
84Fl_Font FltkFont::FontFamily::get (int attrs)
85{
86 int idx = 0;
87 if (attrs & FL_BOLD)
88 idx += 1;
89 if (attrs & FL_ITALIC)
90 idx += 2;
91
92 // should the desired font style not exist, we
93 // return the normal font of the fontFamily
94 return font[idx] >= 0 ? font[idx] : font[0];
95}
96
97
98
100{
101 if (!systemFonts)
103
104 copyAttrs (attrs);
105
106 int fa = 0;
107 if (weight >= 500)
108 fa |= FL_BOLD;
110 fa |= FL_ITALIC;
111
112 object::ConstString nameString (name);
113 FontFamily *family = systemFonts->get (&nameString);
114 if (!family)
115 family = &standardFontFamily;
116
117 font = family->get (fa);
118
119 fl_font(font, size);
120 // WORKAROUND: A bug with fl_width(uint_t) on non-xft X was present in
121 // 1.3.0 (STR #2688).
122 spaceWidth = misc::max(0, (int)fl_width(" ") + letterSpacing);
123 int xx, xy, xw, xh;
124 fl_text_extents("x", xx, xy, xw, xh);
125 xHeight = xh;
126 zeroWidth = (int) fl_width("0");
127 descent = fl_descent();
128 ascent = fl_height() - descent;
129}
130
132{
133 fontsTable->remove (this);
134}
135
136static void strstrip(char *big, const char *little)
137{
138 if (strlen(big) >= strlen(little) &&
139 misc::AsciiStrcasecmp(big + strlen(big) - strlen(little), little) == 0)
140 *(big + strlen(big) - strlen(little)) = '\0';
141}
142
144{
147
148 int k = Fl::set_fonts ("-*-iso10646-1");
149 for (int i = 0; i < k; i++) {
150 int t;
151 char *name = dStrdup (Fl::get_font_name ((Fl_Font) i, &t));
152
153 // normalize font family names (strip off "bold", "italic")
154 if (t & FL_ITALIC)
155 strstrip(name, " italic");
156 if (t & FL_BOLD)
157 strstrip(name, " bold");
158
159 _MSG("Found font: %s%s%s\n", name, t & FL_BOLD ? " bold" : "",
160 t & FL_ITALIC ? " italic" : "");
161
162 object::String *familyName = new object::String(name);
163 free (name);
164 FontFamily *family = systemFonts->get (familyName);
165
166 if (family) {
167 family->set ((Fl_Font) i, t);
168 delete familyName;
169 } else {
170 // set first font of family also as normal font in case there
171 // is no normal (non-bold, non-italic) font
172 family = new FontFamily ((Fl_Font) i, -1, -1, -1);
173 family->set ((Fl_Font) i, t);
174 systemFonts->put (familyName, family);
175 }
176 }
177}
178
179bool
181{
182 if (!systemFonts)
184 object::ConstString familyName (name);
185 return systemFonts->get (&familyName) != NULL;
186}
187
188Fl_Font
189FltkFont::get (const char *name, int attrs)
190{
191 if (!systemFonts)
193 object::ConstString familyName (name);
194 FontFamily *family = systemFonts->get (&familyName);
195 if (family)
196 return family->get (attrs);
197 else
198 return FL_HELVETICA;
199}
200
201bool
203{
204 return FltkFont::fontExists (name);
205}
206
209{
210 FltkFont *font = fontsTable->get (attrs);
211
212 if (font == NULL) {
213 font = new FltkFont (attrs);
214 fontsTable->put (font, font);
215 }
216
217 return font;
218}
219
221 FltkColor>
224 FltkColor> (false, false);
225
226FltkColor::FltkColor (int color): Color (color)
227{
228 this->color = color;
229
231 colors[SHADING_NORMAL] = FL_BLACK;
233 colors[SHADING_INVERSE] = FL_BLACK;
235 colors[SHADING_DARK] = FL_BLACK;
237 colors[SHADING_LIGHT] = FL_BLACK;
238}
239
241{
242 colorsTable->remove (this);
243}
244
246{
247 ColorAttrs attrs(col);
248 FltkColor *color = colorsTable->get (&attrs);
249
250 if (color == NULL) {
251 color = new FltkColor (col);
252 colorsTable->put (color, color);
253 }
254
255 return color;
256}
257
258FltkTooltip::FltkTooltip (const char *text) : Tooltip(text)
259{
260}
261
263{
264 if (in_tooltip || req_tooltip)
265 cancel(); /* cancel tooltip window */
266}
267
269{
270 return new FltkTooltip(text);
271}
272
273/*
274 * Tooltip callback: used to delay it a bit
275 * INVARIANT: Only one instance of this function is requested.
276 */
277static void tooltip_tcb(void *data)
278{
279 req_tooltip = 2;
280 ((FltkTooltip *)data)->onEnter();
281 req_tooltip = 0;
282}
283
285{
286 _MSG("FltkTooltip::onEnter\n");
287 if (!str || !*str)
288 return;
289 if (req_tooltip == 0) {
290 Fl::remove_timeout(tooltip_tcb);
291 Fl::add_timeout(1.0, tooltip_tcb, this);
292 req_tooltip = 1;
293 return;
294 }
295
296 if (!tt_window) {
297 tt_window = new Fl_Menu_Window(0,0,100,24);
298 tt_window->set_override();
299 tt_window->box(FL_NO_BOX);
300 Fl_Box *b = new Fl_Box(0,0,100,24);
301 b->box(FL_BORDER_BOX);
302 b->color(fl_color_cube(FL_NUM_RED-1, FL_NUM_GREEN-1, FL_NUM_BLUE-2));
303 b->labelcolor(FL_BLACK);
304 b->labelfont(FL_HELVETICA);
305 b->labelsize(14);
306 b->align(FL_ALIGN_WRAP|FL_ALIGN_LEFT|FL_ALIGN_INSIDE);
307 tt_window->resizable(b);
308 tt_window->end();
309 }
310
311 /* prepare tooltip window */
312 int x, y;
313 Fl_Box *box = (Fl_Box*)tt_window->child(0);
314 box->label(str);
315 Fl::get_mouse(x,y); y += 6;
316 /* calculate window size */
317 int ww, hh;
318 ww = 800; // max width;
319 box->measure_label(ww, hh);
320 ww += 6 + 2 * Fl::box_dx(box->box());
321 hh += 6 + 2 * Fl::box_dy(box->box());
322 tt_window->resize(x,y,ww,hh);
323 tt_window->show();
324 in_tooltip = 1;
325}
326
327/*
328 * Leaving the widget cancels the tooltip
329 */
331{
332 _MSG(" FltkTooltip::onLeave in_tooltip=%d\n", in_tooltip);
333 cancel();
334}
335
340
341/*
342 * Remove a shown tooltip or cancel a pending one
343 */
345{
346 if (req_tooltip) {
347 Fl::remove_timeout(tooltip_tcb);
348 req_tooltip = 0;
349 }
350 if (!in_tooltip) return;
351 in_tooltip = 0;
352 tt_window->hide();
353
354 /* WORKAROUND: (Black magic here)
355 * Hiding a tooltip with the keyboard or mousewheel doesn't work.
356 * The code below "fixes" the problem */
357 Fl_Widget *widget = Fl::belowmouse();
358 if (widget && widget->window()) {
359 widget->window()->damage(FL_DAMAGE_EXPOSE,0,0,1,1);
360 }
361}
362
364{
365}
366
367void FltkView::addFltkWidget (Fl_Widget *widget,
368 core::Allocation *allocation)
369{
370}
371
372void FltkView::removeFltkWidget (Fl_Widget *widget)
373{
374}
375
376void FltkView::allocateFltkWidget (Fl_Widget *widget,
377 core::Allocation *allocation)
378{
379}
380
381void FltkView::drawFltkWidget (Fl_Widget *widget, core::Rectangle *area)
382{
383}
384
385
392
395 *widget,
396 bool relief)
397{
398 return new ui::FltkComplexButtonResource (platform, widget, relief);
399}
400
403 ::ListResource
404 ::SelectionMode
405 selectionMode, int rows)
406{
407 return new ui::FltkListResource (platform, selectionMode, rows);
408}
409
415
418 bool password,
419 const char *label,
420 const char *placeholder)
421{
422 return new ui::FltkEntryResource (platform, size, password, label,
423 placeholder);
424}
425
428 int rows,
429 const char *placeholder)
430{
431 return new ui::FltkMultiLineTextResource (platform, cols, rows,placeholder);
432}
433
439
442(core::ui::RadioButtonResource *groupedWith, bool activated)
443{
444 return
447 groupedWith,
448 activated);
449}
450
451// ----------------------------------------------------------------------
452
454{
455 DBG_OBJ_CREATE ("dw::fltk::FltkPlatform");
456
457 layout = NULL;
458 idleQueue = new container::typed::List <IdleFunc> (true);
459 idleFuncRunning = false;
460 idleFuncId = 0;
461
462 view = NULL;
463 resources = new container::typed::List <ui::FltkResource> (false);
464
466}
467
469{
470 if (idleFuncRunning)
471 Fl::remove_idle (generalStaticIdle, (void*)this);
472 delete idleQueue;
473 delete resources;
474
476}
477
479{
480 this->layout = layout;
482}
483
484
486{
487 if (this->view)
488 MSG_ERR("FltkPlatform::attachView: multiple views!\n");
489 this->view = (FltkView*)view;
490
491 for (container::typed::Iterator <ui::FltkResource> it =
492 resources->iterator (); it.hasNext (); ) {
493 ui::FltkResource *resource = it.getNext ();
494 resource->attachView (this->view);
495 }
496}
497
498
500{
501 if (this->view != view)
502 MSG_ERR("FltkPlatform::detachView: this->view: %p view: %p\n",
503 (void *) this->view, (void *) view);
504
505 for (container::typed::Iterator <ui::FltkResource> it =
506 resources->iterator (); it.hasNext (); ) {
507 ui::FltkResource *resource = it.getNext ();
508 resource->detachView ((FltkView*)view);
509 }
510 this->view = NULL;
511}
512
513
514int FltkPlatform::textWidth (core::style::Font *font, const char *text,
515 int len)
516{
517 char chbuf[4];
518 int c, cu;
519 int width = 0;
520 FltkFont *ff = (FltkFont*) font;
521 int curr = 0, next = 0, nb;
522
524 int sc_fontsize = lout::misc::roundInt(ff->size * 0.78);
525 for (curr = 0; next < len; curr = next) {
526 next = nextGlyph(text, curr);
527 c = fl_utf8decode(text + curr, text + next, &nb);
528 if ((cu = fl_toupper(c)) == c) {
529 /* already uppercase, just draw the character */
530 fl_font(ff->font, ff->size);
531 if (fl_nonspacing(cu) == 0) {
532 width += font->letterSpacing;
533 width += (int)fl_width(text + curr, next - curr);
534 }
535 } else {
536 /* make utf8 string for converted char */
537 nb = fl_utf8encode(cu, chbuf);
538 fl_font(ff->font, sc_fontsize);
539 if (fl_nonspacing(cu) == 0) {
540 width += font->letterSpacing;
541 width += (int)fl_width(chbuf, nb);
542 }
543 }
544 }
545 } else {
546 fl_font (ff->font, ff->size);
547 width = (int) fl_width (text, len);
548
549 if (font->letterSpacing) {
550 int curr = 0, next = 0;
551
552 while (next < len) {
553 next = nextGlyph(text, curr);
554 c = fl_utf8decode(text + curr, text + next, &nb);
555 if (fl_nonspacing(c) == 0)
556 width += font->letterSpacing;
557 curr = next;
558 }
559 }
560 }
561
562 return width;
563}
564
565char *FltkPlatform::textToUpper (const char *text, int len)
566{
567 char *newstr = NULL;
568
569 if (len > 0) {
570 int newlen;
571
572 newstr = (char*) malloc(3 * len + 1);
573 newlen = fl_utf_toupper((const unsigned char*)text, len, newstr);
574 assert(newlen <= 3 * len);
575 newstr[newlen] = '\0';
576 }
577 return newstr;
578}
579
580char *FltkPlatform::textToLower (const char *text, int len)
581{
582 char *newstr = NULL;
583
584 if (len > 0) {
585 int newlen;
586
587 newstr = (char*) malloc(3 * len + 1);
588 newlen = fl_utf_tolower((const unsigned char*)text, len, newstr);
589 assert(newlen <= 3 * len);
590 newstr[newlen] = '\0';
591 }
592 return newstr;
593}
594
595int FltkPlatform::nextGlyph (const char *text, int idx)
596{
597 return fl_utf8fwd (&text[idx + 1], text, &text[strlen (text)]) - text;
598}
599
600int FltkPlatform::prevGlyph (const char *text, int idx)
601{
602 return fl_utf8back (&text[idx - 1], text, &text[strlen (text)]) - text;
603}
604
606{
607 float horizontal, vertical;
608
609 Fl::screen_dpi(horizontal, vertical);
610 return horizontal;
611}
612
614{
615 float horizontal, vertical;
616
617 Fl::screen_dpi(horizontal, vertical);
618 return vertical;
619}
620
622{
623 ((FltkPlatform*)data)->generalIdle();
624}
625
627{
628 IdleFunc *idleFunc;
629
630 if (!idleQueue->isEmpty ()) {
631 /* Execute the first function in the list. */
632 idleFunc = idleQueue->getFirst ();
633 (layout->*(idleFunc->func)) ();
634
635 /* Remove this function. */
636 idleQueue->removeRef(idleFunc);
637 }
638
639 if (idleQueue->isEmpty()) {
640 idleFuncRunning = false;
641 Fl::remove_idle (generalStaticIdle, (void*)this);
642 }
643}
644
649{
650 /*
651 * Since ... (todo) we have to wrap around fltk_add_idle. There is only one
652 * idle function, the passed idle function is put into a queue.
653 */
654 if (!idleFuncRunning) {
655 Fl::add_idle (generalStaticIdle, (void*)this);
656 idleFuncRunning = true;
657 }
658
659 idleFuncId++;
660
661 IdleFunc *idleFunc = new IdleFunc();
662 idleFunc->id = idleFuncId;
663 idleFunc->func = func;
664 idleQueue->append (idleFunc);
665
666 return idleFuncId;
667}
668
670{
671 bool found;
672 container::typed::Iterator <IdleFunc> it;
673 IdleFunc *idleFunc;
674
675 for (found = false, it = idleQueue->iterator(); !found && it.hasNext(); ) {
676 idleFunc = it.getNext();
677 if (idleFunc->id == idleId) {
678 idleQueue->removeRef (idleFunc);
679 found = true;
680 }
681 }
682
683 if (idleFuncRunning && idleQueue->isEmpty())
684 Fl::remove_idle (generalStaticIdle, (void*)this);
685}
686
688 *attrs,
689 bool tryEverything)
690{
691 return FltkFont::create (attrs);
692}
693
695{
696 return FltkColor::create (color);
697}
698
700{
701 return FltkTooltip::create (text);
702}
703
704void FltkPlatform::copySelection(const char *text, int destination)
705{
706 Fl::copy(text, strlen(text), destination);
707}
708
710 int width, int height, double gamma)
711{
712 return new FltkImgbuf (type, width, height, gamma);
713}
714
719
720
722{
723 resources->append (resource);
724 resource->attachView (view);
725}
726
728{
729 resources->removeRef (resource);
730}
731
732} // namespace fltk
733} // namespace dw
#define _MSG(...)
Definition bookmarks.c:45
The platform independent interface for image buffers.
Definition imgbuf.hh:162
The central class for managing and drawing a widget tree.
Definition layout.hh:37
dw::core::Shape implementation for simple rectangles.
Definition types.hh:70
An interface to encapsulate platform dependent drawing.
Definition view.hh:17
The base class of all dillo widgets.
Definition widget.hh:44
int shadeColor(int color, int d)
Definition style.cc:472
FontVariant fontVariant
Definition style.hh:688
void copyAttrs(FontAttrs *attrs)
Definition style.cc:428
Interface for labelled buttons resources.
Definition ui.hh:400
A factory for the common resource.
Definition ui.hh:581
static FltkColor * create(int color)
static lout::container::typed::HashTable< dw::core::style::ColorAttrs, FltkColor > * colorsTable
int colors[SHADING_NUM]
FontFamily(Fl_Font fontNormal, Fl_Font fontBold, Fl_Font fontItalic, Fl_Font fontBoldItalic)
void set(Fl_Font, int attrs)
FltkFont(core::style::FontAttrs *attrs)
static FontFamily standardFontFamily
static bool fontExists(const char *name)
static FltkFont * create(core::style::FontAttrs *attrs)
static lout::container::typed::HashTable< lout::object::ConstString, FontFamily > * systemFonts
static Fl_Font get(const char *name, int attrs)
static void initSystemFonts()
static lout::container::typed::HashTable< dw::core::style::FontAttrs, FltkFont > * fontsTable
core::ui::LabelButtonResource * createLabelButtonResource(const char *label)
core::ui::OptionMenuResource * createOptionMenuResource()
core::ui::ComplexButtonResource * createComplexButtonResource(core::Widget *widget, bool relief)
core::ui::RadioButtonResource * createRadioButtonResource(core::ui::RadioButtonResource *groupedWith, bool activated)
core::ui::MultiLineTextResource * createMultiLineTextResource(int cols, int rows, const char *placeholder)
core::ui::ListResource * createListResource(core::ui::ListResource::SelectionMode selectionMode, int rows)
void setPlatform(FltkPlatform *platform)
core::ui::EntryResource * createEntryResource(int size, bool password, const char *label, const char *placeholder)
core::ui::CheckButtonResource * createCheckButtonResource(bool activated)
void(core::Layout::* func)()
static void generalStaticIdle(void *data)
float dpiX()
Return screen resolution in x-direction.
int nextGlyph(const char *text, int idx)
Return the index of the next glyph in string text.
int addIdle(void(core::Layout::*func)())
core::Imgbuf * createImgbuf(core::Imgbuf::Type type, int width, int height, double gamma)
Create a (platform specific) image buffer.
int prevGlyph(const char *text, int idx)
Return the index of the previous glyph in string text.
void copySelection(const char *text, int destination)
Copy selected text (0-terminated).
void setLayout(core::Layout *layout)
This methods notifies the platform, that it has been attached to a layout.
bool fontExists(const char *name)
void removeIdle(int idleId)
Remove an idle function, which has not been processed yet.
core::style::Color * createColor(int color)
Create a color resource for a given 0xrrggbb value.
FltkResourceFactory resourceFactory
lout::container::typed::List< ui::FltkResource > * resources
float dpiY()
Return screen resolution in y-direction.
void attachResource(ui::FltkResource *resource)
lout::container::typed::List< IdleFunc > * idleQueue
char * textToLower(const char *text, int len)
Return the string resulting from transforming text to lowercase.
core::style::Tooltip * createTooltip(const char *text)
Create a tooltip.
core::ui::ResourceFactory * getResourceFactory()
...
void detachResource(ui::FltkResource *resource)
void detachView(core::View *view)
This methods notifies the platform, that a view has been detached from the related layout.
core::style::Font * createFont(core::style::FontAttrs *attrs, bool tryEverything)
Create a (platform dependent) font.
int textWidth(core::style::Font *font, const char *text, int len)
Return the width of a text, with a given length and font.
void attachView(core::View *view)
This methods notifies the platform, that a view has been attached to the related layout.
void cancelTooltip()
Cancel a tooltip (either shown or requested)
char * textToUpper(const char *text, int len)
Return the string resulting from transforming text to uppercase.
static FltkTooltip * create(const char *text)
FltkTooltip(const char *text)
This interface adds some more methods for all flkt-based views.
virtual void drawFltkWidget(Fl_Widget *widget, core::Rectangle *area)
virtual void removeFltkWidget(Fl_Widget *widget)
virtual void addFltkWidget(Fl_Widget *widget, core::Allocation *allocation)
virtual void allocateFltkWidget(Fl_Widget *widget, core::Allocation *allocation)
virtual void detachView(FltkView *view)
Definition fltkui.cc:461
virtual void attachView(FltkView *view)
Definition fltkui.cc:444
Typed version of container::untyped::HashTable.
Definition container.hh:536
An object::Object wrapper for constant strings (char*).
Definition object.hh:183
An object::Object wrapper for strings (char*).
Definition object.hh:206
#define DBG_OBJ_DELETE()
#define DBG_OBJ_CREATE(klass)
#define DBG_OBJ_ASSOC_CHILD(child)
char * dStrdup(const char *s)
Definition dlib.c:77
#define MSG_ERR(...)
Definition dpid_common.h:23
static FltkPlatform * platform
static Fl_Menu_Window * tt_window
static int in_tooltip
static int req_tooltip
@ FONT_VARIANT_SMALL_CAPS
Definition style.hh:334
static void strstrip(char *big, const char *little)
static void tooltip_tcb(void *data)
Dw is in this namespace, or sub namespaces of this one.
T max(T a, T b)
Definition misc.hh:41
int AsciiStrcasecmp(const char *s1, const char *s2)
Definition misc.hh:97
int roundInt(double d)
Definition misc.hh:82
Represents the allocation, i.e.
Definition types.hh:164