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