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