Dillo v3.1.1-46-g8a360e32
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 descent = fl_descent();
126 ascent = fl_height() - descent;
127}
128
130{
131 fontsTable->remove (this);
132}
133
134static void strstrip(char *big, const char *little)
135{
136 if (strlen(big) >= strlen(little) &&
137 misc::AsciiStrcasecmp(big + strlen(big) - strlen(little), little) == 0)
138 *(big + strlen(big) - strlen(little)) = '\0';
139}
140
142{
145
146 int k = Fl::set_fonts ("-*-iso10646-1");
147 for (int i = 0; i < k; i++) {
148 int t;
149 char *name = dStrdup (Fl::get_font_name ((Fl_Font) i, &t));
150
151 // normalize font family names (strip off "bold", "italic")
152 if (t & FL_ITALIC)
153 strstrip(name, " italic");
154 if (t & FL_BOLD)
155 strstrip(name, " bold");
156
157 _MSG("Found font: %s%s%s\n", name, t & FL_BOLD ? " bold" : "",
158 t & FL_ITALIC ? " italic" : "");
159
160 object::String *familyName = new object::String(name);
161 free (name);
162 FontFamily *family = systemFonts->get (familyName);
163
164 if (family) {
165 family->set ((Fl_Font) i, t);
166 delete familyName;
167 } else {
168 // set first font of family also as normal font in case there
169 // is no normal (non-bold, non-italic) font
170 family = new FontFamily ((Fl_Font) i, -1, -1, -1);
171 family->set ((Fl_Font) i, t);
172 systemFonts->put (familyName, family);
173 }
174 }
175}
176
177bool
179{
180 if (!systemFonts)
182 object::ConstString familyName (name);
183 return systemFonts->get (&familyName) != NULL;
184}
185
186Fl_Font
187FltkFont::get (const char *name, int attrs)
188{
189 if (!systemFonts)
191 object::ConstString familyName (name);
192 FontFamily *family = systemFonts->get (&familyName);
193 if (family)
194 return family->get (attrs);
195 else
196 return FL_HELVETICA;
197}
198
199bool
201{
202 return FltkFont::fontExists (name);
203}
204
207{
208 FltkFont *font = fontsTable->get (attrs);
209
210 if (font == NULL) {
211 font = new FltkFont (attrs);
212 fontsTable->put (font, font);
213 }
214
215 return font;
216}
217
219 FltkColor>
222 FltkColor> (false, false);
223
224FltkColor::FltkColor (int color): Color (color)
225{
226 this->color = color;
227
229 colors[SHADING_NORMAL] = FL_BLACK;
231 colors[SHADING_INVERSE] = FL_BLACK;
233 colors[SHADING_DARK] = FL_BLACK;
235 colors[SHADING_LIGHT] = FL_BLACK;
236}
237
239{
240 colorsTable->remove (this);
241}
242
244{
245 ColorAttrs attrs(col);
246 FltkColor *color = colorsTable->get (&attrs);
247
248 if (color == NULL) {
249 color = new FltkColor (col);
250 colorsTable->put (color, color);
251 }
252
253 return color;
254}
255
256FltkTooltip::FltkTooltip (const char *text) : Tooltip(text)
257{
258}
259
261{
262 if (in_tooltip || req_tooltip)
263 cancel(); /* cancel tooltip window */
264}
265
267{
268 return new FltkTooltip(text);
269}
270
271/*
272 * Tooltip callback: used to delay it a bit
273 * INVARIANT: Only one instance of this function is requested.
274 */
275static void tooltip_tcb(void *data)
276{
277 req_tooltip = 2;
278 ((FltkTooltip *)data)->onEnter();
279 req_tooltip = 0;
280}
281
283{
284 _MSG("FltkTooltip::onEnter\n");
285 if (!str || !*str)
286 return;
287 if (req_tooltip == 0) {
288 Fl::remove_timeout(tooltip_tcb);
289 Fl::add_timeout(1.0, tooltip_tcb, this);
290 req_tooltip = 1;
291 return;
292 }
293
294 if (!tt_window) {
295 tt_window = new Fl_Menu_Window(0,0,100,24);
296 tt_window->set_override();
297 tt_window->box(FL_NO_BOX);
298 Fl_Box *b = new Fl_Box(0,0,100,24);
299 b->box(FL_BORDER_BOX);
300 b->color(fl_color_cube(FL_NUM_RED-1, FL_NUM_GREEN-1, FL_NUM_BLUE-2));
301 b->labelcolor(FL_BLACK);
302 b->labelfont(FL_HELVETICA);
303 b->labelsize(14);
304 b->align(FL_ALIGN_WRAP|FL_ALIGN_LEFT|FL_ALIGN_INSIDE);
305 tt_window->resizable(b);
306 tt_window->end();
307 }
308
309 /* prepare tooltip window */
310 int x, y;
311 Fl_Box *box = (Fl_Box*)tt_window->child(0);
312 box->label(str);
313 Fl::get_mouse(x,y); y += 6;
314 /* calculate window size */
315 int ww, hh;
316 ww = 800; // max width;
317 box->measure_label(ww, hh);
318 ww += 6 + 2 * Fl::box_dx(box->box());
319 hh += 6 + 2 * Fl::box_dy(box->box());
320 tt_window->resize(x,y,ww,hh);
321 tt_window->show();
322 in_tooltip = 1;
323}
324
325/*
326 * Leaving the widget cancels the tooltip
327 */
329{
330 _MSG(" FltkTooltip::onLeave in_tooltip=%d\n", in_tooltip);
331 cancel();
332}
333
338
339/*
340 * Remove a shown tooltip or cancel a pending one
341 */
343{
344 if (req_tooltip) {
345 Fl::remove_timeout(tooltip_tcb);
346 req_tooltip = 0;
347 }
348 if (!in_tooltip) return;
349 in_tooltip = 0;
350 tt_window->hide();
351
352 /* WORKAROUND: (Black magic here)
353 * Hiding a tooltip with the keyboard or mousewheel doesn't work.
354 * The code below "fixes" the problem */
355 Fl_Widget *widget = Fl::belowmouse();
356 if (widget && widget->window()) {
357 widget->window()->damage(FL_DAMAGE_EXPOSE,0,0,1,1);
358 }
359}
360
362{
363}
364
365void FltkView::addFltkWidget (Fl_Widget *widget,
366 core::Allocation *allocation)
367{
368}
369
370void FltkView::removeFltkWidget (Fl_Widget *widget)
371{
372}
373
374void FltkView::allocateFltkWidget (Fl_Widget *widget,
375 core::Allocation *allocation)
376{
377}
378
379void FltkView::drawFltkWidget (Fl_Widget *widget, core::Rectangle *area)
380{
381}
382
383
390
393 *widget,
394 bool relief)
395{
396 return new ui::FltkComplexButtonResource (platform, widget, relief);
397}
398
401 ::ListResource
402 ::SelectionMode
403 selectionMode, int rows)
404{
405 return new ui::FltkListResource (platform, selectionMode, rows);
406}
407
413
416 bool password,
417 const char *label,
418 const char *placeholder)
419{
420 return new ui::FltkEntryResource (platform, size, password, label,
421 placeholder);
422}
423
426 int rows,
427 const char *placeholder)
428{
429 return new ui::FltkMultiLineTextResource (platform, cols, rows,placeholder);
430}
431
437
440(core::ui::RadioButtonResource *groupedWith, bool activated)
441{
442 return
445 groupedWith,
446 activated);
447}
448
449// ----------------------------------------------------------------------
450
452{
453 DBG_OBJ_CREATE ("dw::fltk::FltkPlatform");
454
455 layout = NULL;
456 idleQueue = new container::typed::List <IdleFunc> (true);
457 idleFuncRunning = false;
458 idleFuncId = 0;
459
460 view = NULL;
461 resources = new container::typed::List <ui::FltkResource> (false);
462
464}
465
467{
468 if (idleFuncRunning)
469 Fl::remove_idle (generalStaticIdle, (void*)this);
470 delete idleQueue;
471 delete resources;
472
474}
475
477{
478 this->layout = layout;
480}
481
482
484{
485 if (this->view)
486 MSG_ERR("FltkPlatform::attachView: multiple views!\n");
487 this->view = (FltkView*)view;
488
489 for (container::typed::Iterator <ui::FltkResource> it =
490 resources->iterator (); it.hasNext (); ) {
491 ui::FltkResource *resource = it.getNext ();
492 resource->attachView (this->view);
493 }
494}
495
496
498{
499 if (this->view != view)
500 MSG_ERR("FltkPlatform::detachView: this->view: %p view: %p\n",
501 (void *) this->view, (void *) view);
502
503 for (container::typed::Iterator <ui::FltkResource> it =
504 resources->iterator (); it.hasNext (); ) {
505 ui::FltkResource *resource = it.getNext ();
506 resource->detachView ((FltkView*)view);
507 }
508 this->view = NULL;
509}
510
511
512int FltkPlatform::textWidth (core::style::Font *font, const char *text,
513 int len)
514{
515 char chbuf[4];
516 int c, cu;
517 int width = 0;
518 FltkFont *ff = (FltkFont*) font;
519 int curr = 0, next = 0, nb;
520
522 int sc_fontsize = lout::misc::roundInt(ff->size * 0.78);
523 for (curr = 0; next < len; curr = next) {
524 next = nextGlyph(text, curr);
525 c = fl_utf8decode(text + curr, text + next, &nb);
526 if ((cu = fl_toupper(c)) == c) {
527 /* already uppercase, just draw the character */
528 fl_font(ff->font, ff->size);
529 if (fl_nonspacing(cu) == 0) {
530 width += font->letterSpacing;
531 width += (int)fl_width(text + curr, next - curr);
532 }
533 } else {
534 /* make utf8 string for converted char */
535 nb = fl_utf8encode(cu, chbuf);
536 fl_font(ff->font, sc_fontsize);
537 if (fl_nonspacing(cu) == 0) {
538 width += font->letterSpacing;
539 width += (int)fl_width(chbuf, nb);
540 }
541 }
542 }
543 } else {
544 fl_font (ff->font, ff->size);
545 width = (int) fl_width (text, len);
546
547 if (font->letterSpacing) {
548 int curr = 0, next = 0;
549
550 while (next < len) {
551 next = nextGlyph(text, curr);
552 c = fl_utf8decode(text + curr, text + next, &nb);
553 if (fl_nonspacing(c) == 0)
554 width += font->letterSpacing;
555 curr = next;
556 }
557 }
558 }
559
560 return width;
561}
562
563char *FltkPlatform::textToUpper (const char *text, int len)
564{
565 char *newstr = NULL;
566
567 if (len > 0) {
568 int newlen;
569
570 newstr = (char*) malloc(3 * len + 1);
571 newlen = fl_utf_toupper((const unsigned char*)text, len, newstr);
572 assert(newlen <= 3 * len);
573 newstr[newlen] = '\0';
574 }
575 return newstr;
576}
577
578char *FltkPlatform::textToLower (const char *text, int len)
579{
580 char *newstr = NULL;
581
582 if (len > 0) {
583 int newlen;
584
585 newstr = (char*) malloc(3 * len + 1);
586 newlen = fl_utf_tolower((const unsigned char*)text, len, newstr);
587 assert(newlen <= 3 * len);
588 newstr[newlen] = '\0';
589 }
590 return newstr;
591}
592
593int FltkPlatform::nextGlyph (const char *text, int idx)
594{
595 return fl_utf8fwd (&text[idx + 1], text, &text[strlen (text)]) - text;
596}
597
598int FltkPlatform::prevGlyph (const char *text, int idx)
599{
600 return fl_utf8back (&text[idx - 1], text, &text[strlen (text)]) - text;
601}
602
604{
605 float horizontal, vertical;
606
607 Fl::screen_dpi(horizontal, vertical);
608 return horizontal;
609}
610
612{
613 float horizontal, vertical;
614
615 Fl::screen_dpi(horizontal, vertical);
616 return vertical;
617}
618
620{
621 ((FltkPlatform*)data)->generalIdle();
622}
623
625{
626 IdleFunc *idleFunc;
627
628 if (!idleQueue->isEmpty ()) {
629 /* Execute the first function in the list. */
630 idleFunc = idleQueue->getFirst ();
631 (layout->*(idleFunc->func)) ();
632
633 /* Remove this function. */
634 idleQueue->removeRef(idleFunc);
635 }
636
637 if (idleQueue->isEmpty()) {
638 idleFuncRunning = false;
639 Fl::remove_idle (generalStaticIdle, (void*)this);
640 }
641}
642
647{
648 /*
649 * Since ... (todo) we have to wrap around fltk_add_idle. There is only one
650 * idle function, the passed idle function is put into a queue.
651 */
652 if (!idleFuncRunning) {
653 Fl::add_idle (generalStaticIdle, (void*)this);
654 idleFuncRunning = true;
655 }
656
657 idleFuncId++;
658
659 IdleFunc *idleFunc = new IdleFunc();
660 idleFunc->id = idleFuncId;
661 idleFunc->func = func;
662 idleQueue->append (idleFunc);
663
664 return idleFuncId;
665}
666
668{
669 bool found;
670 container::typed::Iterator <IdleFunc> it;
671 IdleFunc *idleFunc;
672
673 for (found = false, it = idleQueue->iterator(); !found && it.hasNext(); ) {
674 idleFunc = it.getNext();
675 if (idleFunc->id == idleId) {
676 idleQueue->removeRef (idleFunc);
677 found = true;
678 }
679 }
680
681 if (idleFuncRunning && idleQueue->isEmpty())
682 Fl::remove_idle (generalStaticIdle, (void*)this);
683}
684
686 *attrs,
687 bool tryEverything)
688{
689 return FltkFont::create (attrs);
690}
691
693{
694 return FltkColor::create (color);
695}
696
698{
699 return FltkTooltip::create (text);
700}
701
702void FltkPlatform::copySelection(const char *text)
703{
704 Fl::copy(text, strlen(text), 0);
705}
706
708 int width, int height, double gamma)
709{
710 return new FltkImgbuf (type, width, height, gamma);
711}
712
717
718
720{
721 resources->append (resource);
722 resource->attachView (view);
723}
724
726{
727 resources->removeRef (resource);
728}
729
730} // namespace fltk
731} // 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:687
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: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:21
int AsciiStrcasecmp(const char *s1, const char *s2)
Definition misc.hh:77
int roundInt(double d)
Definition misc.hh:62
Represents the allocation, i.e.
Definition types.hh:164