diff options
author | Johannes Hofmann <Johannes.Hofmann@gmx.de> | 2011-09-19 21:33:52 +0200 |
---|---|---|
committer | Johannes Hofmann <Johannes.Hofmann@gmx.de> | 2011-09-19 21:33:52 +0200 |
commit | abd446c2eebe1f96764b6d95f1c6c61ae9bc40b2 (patch) | |
tree | b313bbeebf50fd53369d303824edab57aa69d016 /dw | |
parent | b0b0cddaff10b4cff371b8bb7aa21e045f8e3915 (diff) | |
parent | 0caf22a3f7c33578a073cee42c6cfa61f971bc42 (diff) |
merge
Diffstat (limited to 'dw')
-rw-r--r-- | dw/findtext.cc | 10 | ||||
-rw-r--r-- | dw/fltkcomplexbutton.cc | 345 | ||||
-rw-r--r-- | dw/fltkcomplexbutton.hh | 54 | ||||
-rw-r--r-- | dw/fltkcore.hh | 2 | ||||
-rw-r--r-- | dw/fltkflatview.cc | 20 | ||||
-rw-r--r-- | dw/fltkflatview.hh | 3 | ||||
-rw-r--r-- | dw/fltkimgbuf.cc | 14 | ||||
-rw-r--r-- | dw/fltkimgbuf.hh | 2 | ||||
-rw-r--r-- | dw/fltkmisc.cc | 11 | ||||
-rw-r--r-- | dw/fltkplatform.cc | 370 | ||||
-rw-r--r-- | dw/fltkplatform.hh | 33 | ||||
-rw-r--r-- | dw/fltkpreview.cc | 56 | ||||
-rw-r--r-- | dw/fltkpreview.hh | 15 | ||||
-rw-r--r-- | dw/fltkui.cc | 792 | ||||
-rw-r--r-- | dw/fltkui.hh | 134 | ||||
-rw-r--r-- | dw/fltkviewbase.cc | 542 | ||||
-rw-r--r-- | dw/fltkviewbase.hh | 61 | ||||
-rw-r--r-- | dw/fltkviewport.cc | 284 | ||||
-rw-r--r-- | dw/fltkviewport.hh | 22 | ||||
-rw-r--r-- | dw/image.cc | 15 | ||||
-rw-r--r-- | dw/layout.cc | 77 | ||||
-rw-r--r-- | dw/layout.hh | 10 | ||||
-rw-r--r-- | dw/platform.hh | 5 | ||||
-rw-r--r-- | dw/selection.cc | 132 | ||||
-rw-r--r-- | dw/selection.hh | 40 | ||||
-rw-r--r-- | dw/style.cc | 339 | ||||
-rw-r--r-- | dw/table.cc | 10 | ||||
-rw-r--r-- | dw/textblock.cc | 110 | ||||
-rw-r--r-- | dw/textblock.hh | 4 | ||||
-rw-r--r-- | dw/types.cc | 11 | ||||
-rw-r--r-- | dw/types.hh | 3 | ||||
-rw-r--r-- | dw/ui.cc | 4 | ||||
-rw-r--r-- | dw/ui.hh | 2 | ||||
-rw-r--r-- | dw/view.hh | 14 | ||||
-rw-r--r-- | dw/widget.hh | 14 |
35 files changed, 1868 insertions, 1692 deletions
diff --git a/dw/findtext.cc b/dw/findtext.cc index f3e0ba20..9793db91 100644 --- a/dw/findtext.cc +++ b/dw/findtext.cc @@ -37,7 +37,7 @@ FindtextState::FindtextState () FindtextState::~FindtextState () { if (key) - delete key; + free(key); if (nexttab) delete[] nexttab; if (iterator) @@ -52,7 +52,7 @@ void FindtextState::setWidget (Widget *widget) // A widget change will restart the search. if (key) - delete key; + free(key); key = NULL; if (nexttab) delete[] nexttab; @@ -81,7 +81,7 @@ FindtextState::Result FindtextState::search (const char *key, bool caseSens, strcmp (this->key, key) != 0) { newKey = true; if (this->key) - delete this->key; + free(this->key); this->key = strdup (key); this->caseSens = caseSens; @@ -106,7 +106,7 @@ FindtextState::Result FindtextState::search (const char *key, bool caseSens, bool firstTrial = !wasHighlighted || newKey; if (search0 (backwards, firstTrial)) { - // Highlighlighting is done with a clone. + // Highlighting is done with a clone. hlIterator = iterator->cloneCharIterator (); for (int i = 0; key[i]; i++) hlIterator->next (); @@ -147,7 +147,7 @@ void FindtextState::resetSearch () unhighlight (); if (key) - delete key; + free(key); key = NULL; } diff --git a/dw/fltkcomplexbutton.cc b/dw/fltkcomplexbutton.cc index f80d0eb0..89295190 100644 --- a/dw/fltkcomplexbutton.cc +++ b/dw/fltkcomplexbutton.cc @@ -1,7 +1,5 @@ - -// fltkcomplexbutton.cc contains code from FLTK2's src/Button.cxx -// that is Copyright 1998-2006 by Bill Spitzak and others. -// (see http://svn.easysw.com/public/fltk/fltk/trunk/src/Button.cxx) +// fltkcomplexbutton.cc contains code from FLTK 1.3's src/Fl_Button.cxx +// that is Copyright 1998-2010 by Bill Spitzak and others. /* * This program is free software; you can redistribute it and/or modify @@ -18,263 +16,128 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <fltk/events.h> -#include <fltk/damage.h> -#include <fltk/Group.h> -#include <fltk/Box.h> -#include <stdlib.h> +#include <FL/Fl.H> +#include <FL/Fl_Button.H> +#include <FL/Fl_Group.H> +#include <FL/Fl_Window.H> #include "fltkcomplexbutton.hh" -using namespace fltk; using namespace dw::fltk::ui; -/*! \class fltk::ComplexButton - - ComplexButtons generate callbacks when they are clicked by the user. You - control exactly when and how by changing the values for when(): - - fltk::WHEN_NEVER: The callback is not done, instead changed() is - turned on. - - fltk::WHEN_RELEASE: This is the default, the callback is done - after the user successfully clicks the button (i.e. they let it go - with the mouse still pointing at it), or when a shortcut is typed. - - fltk::WHEN_CHANGED : The callback is done each time the value() - changes (when the user pushes and releases the button, and as the - mouse is dragged around in and out of the button). - - ComplexButtons can also generate callbacks in response to fltk::SHORTCUT - events. The button can either have an explicit shortcut() value or a - letter shortcut can be indicated in the label() with an '&' - character before it. For the label shortcut it does not matter if - Alt is held down, but if you have an input field in the same window, - the user will have to hold down the Alt key so that the input field - does not eat the event first as an fltk::KEY event. - - \image html buttons.gif -*/ - -/*! \fn bool ComplexButton::value() const - The current value. True means it is pushed down, false means it is - not pushed down. The ToggleComplexButton subclass provides the ability for - the user to change this value permanently, otherwise it is just - temporary while the user is holding the button down. - - This is the same as Widget::state(). -*/ - -/*! \fn bool ComplexButton::value(bool) - Change the value(). Redraws the button and returns true if the new - value is different. This is the same function as Widget::state(). - See also Widget::set(), Widget::clear(), and Widget::setonly(). - - If you turn it on, a normal button will draw pushed-in, until - the user clicks it and releases it. -*/ - -static bool initial_state; +/** + Sets the current value of the button. + A non-zero value sets the button to 1 (ON), and zero sets it to 0 (OFF). + \param[in] v button value. + */ +int ComplexButton::value(int v) { + v = v ? 1 : 0; + oldval = v; + clear_changed(); + if (value_ != v) { + value_ = v; + if (box()) redraw(); + return 1; + } else { + return 0; + } +} -int ComplexButton::handle(int event) { - return handle(event, Rectangle(w(),h())); +void ComplexButton::draw() { + Fl_Color col = value() ? selection_color() : color(); + draw_box(value() ? (down_box()?down_box():fl_down(box())) : box(), col); + if (Fl::focus() == this) draw_focus(); + + // ComplexButton is a Group; draw its children + for (int i = children () - 1; i >= 0; i--) { + // set absolute coordinates for fltk-1.3 --jcid + child (i)->position(x()+(w()-child(i)->w())/2,y()+(h()-child(i)->h())/2); + draw_child (*child (i)); + } } -int ComplexButton::handle(int event, const Rectangle& rectangle) { +int ComplexButton::handle(int event) { + int newval; switch (event) { - case ENTER: - case LEAVE: - redraw_highlight(); - case MOVE: + case FL_ENTER: /* FALLTHROUGH */ + case FL_LEAVE: return 1; - case PUSH: - if (pushed()) return 1; // ignore extra pushes on currently-pushed button - initial_state = state(); - clear_flag(PUSHED); - /* do_callback(); */ - case DRAG: { - bool inside = event_inside(rectangle); - if (inside) { - if (!flag(PUSHED)) { - set_flag(PUSHED); - redraw(DAMAGE_VALUE); - } - } else { - if (flag(PUSHED)) { - clear_flag(PUSHED); - redraw(DAMAGE_VALUE); - } - } - if (when() & WHEN_CHANGED) { // momentary button must record state() - if (state(inside ? !initial_state : initial_state)) - do_callback(); + case FL_PUSH: + if (Fl::visible_focus() && handle(FL_FOCUS)) Fl::focus(this); + case FL_DRAG: + if (Fl::event_inside(this)) { + newval = !oldval; + } else + { + clear_changed(); + newval = oldval; } - return 1;} - case RELEASE: - if (!flag(PUSHED)) return 1; - clear_flag(PUSHED); - redraw(DAMAGE_VALUE); - if (type() == RADIO) - setonly(); - else if (type() == TOGGLE) - state(!initial_state); - else { - state(initial_state); - if (when() & WHEN_CHANGED) {do_callback(); return 1;} + if (newval != value_) { + value_ = newval; + set_changed(); + redraw(); + if (when() & FL_WHEN_CHANGED) do_callback(); } - if (when() & WHEN_RELEASE) do_callback(); else set_changed(); return 1; - case FOCUS: - redraw(1); // minimal redraw to just add the focus box - // grab initial focus if we are an ReturnComplexButton: - return shortcut()==ReturnKey ? 2 : 1; - case UNFOCUS: - redraw(DAMAGE_HIGHLIGHT); - return 1; - case KEY: - if (event_key() == ' ' || event_key() == ReturnKey - || event_key() == KeypadEnter) goto EXECUTE; - return 0; - case SHORTCUT: - if (!test_shortcut()) return 0; - EXECUTE: - if (type() == RADIO) { - if (!state()) { - setonly(); - if (when() & WHEN_CHANGED) do_callback(); else set_changed(); - } - } else if (type() == TOGGLE) { - state(!state()); - if (when() & WHEN_CHANGED) do_callback(); else set_changed(); + case FL_RELEASE: + if (value_ == oldval) { + if (when() & FL_WHEN_NOT_CHANGED) do_callback(); + return 1; } - if (when() & WHEN_RELEASE) do_callback(); + set_changed(); + value(oldval); + set_changed(); + if (when() & FL_WHEN_CHANGED) { + Fl_Widget_Tracker wp(this); + do_callback(); + if (wp.deleted()) return 1; + } + if (when() & FL_WHEN_RELEASE) do_callback(); return 1; + case FL_FOCUS : /* FALLTHROUGH */ + case FL_UNFOCUS : + if (Fl::visible_focus()) { + if (box() == FL_NO_BOX) { + // Widgets with the FL_NO_BOX boxtype need a parent to + // redraw, since it is responsible for redrawing the + // background... + int X = x() > 0 ? x() - 1 : 0; + int Y = y() > 0 ? y() - 1 : 0; + if (window()) window()->damage(FL_DAMAGE_ALL, X, Y, w() + 2, h() + 2); + } else redraw(); + return 1; + } else return 0; + case FL_KEYBOARD : + if (Fl::focus() == this && Fl::event_key() == ' ' && + !(Fl::event_state() & (FL_SHIFT | FL_CTRL | FL_ALT | FL_META))) { + set_changed(); + Fl_Widget_Tracker wp(this); + if (wp.deleted()) return 1; + if (when() & FL_WHEN_RELEASE) do_callback(); + return 1; + } default: return 0; } } -//////////////////////////////////////////////////////////////// - -#include <fltk/draw.h> - -extern Widget* fl_did_clipping; - -/*! - This function provides a mess of back-compatabilty and Windows - emulation to subclasses of ComplexButton to draw with. It will draw the - button according to the current state of being pushed and it's - state(). If non-zero is passed for \a glyph_width then the glyph() - is drawn in that space on the left (or on the right if negative), - and it assummes the glyph indicates the state(), so the box is only - used to indicate the pushed state. -*/ -void ComplexButton::draw(int glyph_width) const -{ - // For back-compatability, setting color() or box() directly on a plain - // button will cause it to act like buttoncolor() or buttonbox() are - // set: - Style localstyle; - const Style* style = this->style(); - if (!glyph_width) { - localstyle = *style; - if (localstyle.color_) localstyle.buttoncolor_ = localstyle.color_; - if (localstyle.box_) localstyle.buttonbox_ = localstyle.box_; - if (localstyle.labelcolor_) localstyle.textcolor_ = localstyle.labelcolor_; - style = &localstyle; - } - - Box* box = style->buttonbox(); - - Flags box_flags = flags() | OUTPUT; - Flags glyph_flags = box_flags & ~(HIGHLIGHT|OUTPUT); - if (glyph_width) box_flags &= ~STATE; - - // only draw "inside" labels: - Rectangle r(0,0,w(),h()); - - if (box == NO_BOX) { - Color bg; - if (box_flags & HIGHLIGHT && (bg = style->highlight_color())) { - setcolor(bg); - fillrect(r); - } else if (label() || (damage()&(DAMAGE_EXPOSE|DAMAGE_HIGHLIGHT))) { - // erase the background so we can redraw the label in the new color: - draw_background(); - } - // this allows these buttons to be put into browser/menus: - //fg = fl_item_labelcolor(this); - } else { - if ((damage()&(DAMAGE_EXPOSE|DAMAGE_HIGHLIGHT)) - && !box->fills_rectangle()) { - // Erase the area behind non-square boxes - draw_background(); - } - } - - // Draw the box: - drawstyle(style,box_flags); - // For back-compatability we use any directly-set selection_color() - // to color the box: - if (!glyph_width && state() && style->selection_color_) { - setbgcolor(style->selection_color_); - setcolor(contrast(style->selection_textcolor(),style->selection_color_)); - } - box->draw(r); - Rectangle r1(r); box->inset(r1); - - if (glyph_width) { - int g = abs(glyph_width); - Rectangle lr(r1); - Rectangle gr(r1, g, g); - if (glyph_width < 0) { - lr.w(lr.w()-g-3); - gr.x(r1.r()-g-3); - } else { - lr.set_x(g+3); - gr.x(r1.x()+3); - } - this->draw_label(lr, box_flags); - drawstyle(style,glyph_flags); - this->glyph()->draw(gr); - drawstyle(style,box_flags); - } else { - this->draw_label(r1, box_flags); - } - box->draw_symbol_overlay(r); -} - -void ComplexButton::draw() { - if (type() == HIDDEN) { - fl_did_clipping = this; - return; - } - draw(0); - - // ComplexButton is a Group, draw its children - for (int i = children () - 1; i >= 0; i--) - draw_child (*child (i)); +/** + The constructor creates the button using the given position, size and label. + \param[in] X, Y, W, H position and size of the widget + \param[in] L widget label, default is no label + */ +ComplexButton::ComplexButton(int X, int Y, int W, int H, const char *L) +: Fl_Group(X,Y,W,H,L) { + Fl_Group::current(0); + box(FL_UP_BOX); + down_box(FL_NO_BOX); + value_ = oldval = 0; } -//////////////////////////////////////////////////////////////// - -static NamedStyle style("ComplexButton", 0, &ComplexButton::default_style); -NamedStyle* ComplexButton::default_style = &::style; - -ComplexButton::ComplexButton(int x,int y,int w,int h, const char *l) : - Group(x,y,w,h,l) -{ - style(default_style); - highlight_color(GRAY20); - //set_click_to_focus(); +ComplexButton::~ComplexButton() { + /* + * The Fl_Group destructor clear()s the children, but layout expects + * the flat view to be around until it deletes it. + */ + remove(0); } - -//////////////////////////////////////////////////////////////// - -/*! \class fltk::ToggleComplexButton - This button turns the state() on and off each release of a click - inside of it. - - You can also convert a regular button into this by doing - type(ComplexButton::TOGGLE) to it. -*/ - -// -// diff --git a/dw/fltkcomplexbutton.hh b/dw/fltkcomplexbutton.hh index 83160c06..3a14cfb2 100644 --- a/dw/fltkcomplexbutton.hh +++ b/dw/fltkcomplexbutton.hh @@ -1,7 +1,6 @@ -// fltkcomplexbutton.hh contains code from FLTK2's fltk/Button.h -// that is Copyright 2002 by Bill Spitzak and others. -// (see http://svn.easysw.com/public/fltk/fltk/trunk/fltk/Button.h) +// fltkcomplexbutton.hh contains code from FLTK 1.3's FL/Fl_Button.H +// that is Copyright 1998-2010 by Bill Spitzak and others. /* * This program is free software; you can redistribute it and/or modify @@ -21,35 +20,56 @@ #ifndef __FLTK_COMPLEX_BUTTON_HH__ #define __FLTK_COMPLEX_BUTTON_HH__ -#include <fltk/Group.h> +#include <FL/Fl_Group.H> + +extern FL_EXPORT Fl_Shortcut fl_old_shortcut(const char*); namespace dw { namespace fltk { namespace ui { -class ComplexButton: public ::fltk::Group -{ +class FL_EXPORT ComplexButton : public Fl_Group { + + int shortcut_; + char value_; + char oldval; + uchar down_box_; + +protected: + virtual void draw(); + public: - enum {HIDDEN=3}; // back-comptability value to hide the button + virtual int handle(int); - bool value() const { return state(); } - bool value(bool v) { return state(v); } + ComplexButton(int X, int Y, int W, int H, const char *L = 0); + ~ComplexButton(); - int handle(int); - int handle(int event, const Rectangle&); - ComplexButton(int,int,int,int,const char * = 0); - ~ComplexButton() { remove_all ();}; - static ::fltk::NamedStyle* default_style; + int value(int v); - virtual void draw(); - void draw(int glyph_width) const; + /** + Returns the current value of the button (0 or 1). + */ + char value() const {return value_;} + + /** + Returns the current down box type, which is drawn when value() is non-zero. + \retval Fl_Boxtype + */ + Fl_Boxtype down_box() const {return (Fl_Boxtype)down_box_;} + + /** + Sets the down box type. The default value of 0 causes FLTK to figure out + the correct matching down version of box(). + \param[in] b down box type + */ + void down_box(Fl_Boxtype b) {down_box_ = b;} }; } // namespace ui } // namespace fltk } // namespace dw -#endif // __FLTK_COMPLEX_BUTTON_HH__ +#endif // // diff --git a/dw/fltkcore.hh b/dw/fltkcore.hh index fbff3fad..376f588e 100644 --- a/dw/fltkcore.hh +++ b/dw/fltkcore.hh @@ -13,7 +13,7 @@ class FltkResource; } // namespace fltk } // namespace core -#include <fltk/Widget.h> +#include <FL/Fl_Widget.H> #include "core.hh" #include "fltkimgbuf.hh" diff --git a/dw/fltkflatview.cc b/dw/fltkflatview.cc index 85385394..b9e85d99 100644 --- a/dw/fltkflatview.cc +++ b/dw/fltkflatview.cc @@ -21,12 +21,8 @@ #include "fltkflatview.hh" -#include <fltk/draw.h> -#include <fltk/events.h> - #include <stdio.h> -using namespace fltk; using namespace lout::container::typed; namespace dw { @@ -82,24 +78,24 @@ void FltkFlatView::setViewportSize (int width, int height, { } -int FltkFlatView::translateViewXToCanvasX (int x) +int FltkFlatView::translateViewXToCanvasX (int X) { - return x; + return X - x (); } -int FltkFlatView::translateViewYToCanvasY (int y) +int FltkFlatView::translateViewYToCanvasY (int Y) { - return y; + return Y - y (); } -int FltkFlatView::translateCanvasXToViewX (int x) +int FltkFlatView::translateCanvasXToViewX (int X) { - return x; + return X + x (); } -int FltkFlatView::translateCanvasYToViewY (int y) +int FltkFlatView::translateCanvasYToViewY (int Y) { - return y; + return Y + y (); } diff --git a/dw/fltkflatview.hh b/dw/fltkflatview.hh index 5106cbdf..8d84fda9 100644 --- a/dw/fltkflatview.hh +++ b/dw/fltkflatview.hh @@ -1,9 +1,6 @@ #ifndef __DW_FLTKFLATVIEW_HH__ #define __DW_FLTKFLATVIEW_HH__ -#include <fltk/Group.h> -#include <fltk/Scrollbar.h> - #include "core.hh" #include "fltkcore.hh" #include "fltkviewbase.hh" diff --git a/dw/fltkimgbuf.cc b/dw/fltkimgbuf.cc index e3be41a9..97cbc1b4 100644 --- a/dw/fltkimgbuf.cc +++ b/dw/fltkimgbuf.cc @@ -23,13 +23,10 @@ #include "../lout/msg.h" #include "../lout/misc.hh" -#include <fltk/draw.h> -#include <fltk/Color.h> +#include <FL/fl_draw.H> #define IMAGE_MAX_AREA (6000 * 6000) -using namespace fltk; - namespace dw { namespace fltk { @@ -302,7 +299,7 @@ int FltkImgbuf::scaledY(int ySrc) return ySrc * height / root->height; } -void FltkImgbuf::draw (::fltk::Widget *target, int xRoot, int yRoot, +void FltkImgbuf::draw (Fl_Widget *target, int xRoot, int yRoot, int x, int y, int width, int height) { // TODO: Clarify the question, whether "target" is the current widget @@ -324,10 +321,9 @@ void FltkImgbuf::draw (::fltk::Widget *target, int xRoot, int yRoot, height = this->height - y; } - // Draw - ::fltk::Rectangle rect (xRoot + x, yRoot + y, width, height); - PixelType ptype = (type == RGBA) ? ::fltk::RGBA : ::fltk::RGB; - drawimage(rawdata+bpp*(y*this->width + x),ptype,rect,bpp*this->width); + fl_draw_image(rawdata+bpp*(y*this->width + x), xRoot + x, yRoot + y, width, + height, bpp, this->width * bpp); + } } // namespace dw diff --git a/dw/fltkimgbuf.hh b/dw/fltkimgbuf.hh index 54d9ca34..30e0cc37 100644 --- a/dw/fltkimgbuf.hh +++ b/dw/fltkimgbuf.hh @@ -55,7 +55,7 @@ public: void setDeleteOnUnref (bool deleteOnUnref); bool isReferred (); - void draw (::fltk::Widget *target, int xRoot, int yRoot, + void draw (Fl_Widget *target, int xRoot, int yRoot, int x, int y, int width, int height); }; diff --git a/dw/fltkmisc.cc b/dw/fltkmisc.cc index 5d20a87a..01024f25 100644 --- a/dw/fltkmisc.cc +++ b/dw/fltkmisc.cc @@ -18,11 +18,10 @@ */ - +#include "../lout/msg.h" #include "fltkmisc.hh" -#include <fltk/events.h> -#include <fltk/Monitor.h> +#include <FL/Fl.H> #include <stdio.h> namespace dw { @@ -31,17 +30,17 @@ namespace misc { int screenWidth () { - return ::fltk::Monitor::all ().w (); + return Fl::w (); } int screenHeight () { - return ::fltk::Monitor::all ().h (); + return Fl::h (); } void warpPointer (int x, int y) { - ::fltk::warp_mouse (x, y); + MSG_ERR("no warpPointer mechanism available.\n"); } } // namespace misc diff --git a/dw/fltkplatform.cc b/dw/fltkplatform.cc index 17eb5d51..68819c91 100644 --- a/dw/fltkplatform.cc +++ b/dw/fltkplatform.cc @@ -18,24 +18,36 @@ */ #include <stdio.h> -#include <wchar.h> -#include <wctype.h> #include "../lout/msg.h" #include "fltkcore.hh" -#include <fltk/draw.h> -#include <fltk/run.h> -#include <fltk/events.h> -#include <fltk/Monitor.h> -#include <fltk/InvisibleBox.h> -#include <fltk/Tooltip.h> -#include <fltk/utf.h> +#include <FL/fl_draw.H> +#include <FL/Fl_Box.H> +#include <FL/Fl_Tooltip.H> +#include <FL/Fl_Menu_Window.H> +#include <FL/Fl_Paged_Device.H> + +/* + * Local data + */ + +/* Use of Fl_Text_Display links in a lot of printer code that we don't have + * any need for currently. This stub prevents that. */ +class FL_EXPORT Fl_Printer : public Fl_Paged_Device { +public: + static const char *class_id; + Fl_Printer(void) {}; +}; +const char *Fl_Printer::class_id = "Fl_Printer"; + +/* Tooltips */ +static Fl_Menu_Window *tt_window = NULL; +static int in_tooltip = 0, req_tooltip = 0; namespace dw { namespace fltk { -using namespace ::fltk; using namespace lout; /** @@ -47,37 +59,78 @@ container::typed::HashTable <dw::core::style::FontAttrs, new container::typed::HashTable <dw::core::style::FontAttrs, FltkFont> (false, false); +container::typed::HashTable <lout::object::ConstString, + FltkFont::FontFamily> *FltkFont::systemFonts = + NULL; + +FltkFont::FontFamily FltkFont::standardFontFamily (FL_HELVETICA, + FL_HELVETICA_BOLD, + FL_HELVETICA_ITALIC, + FL_HELVETICA_BOLD_ITALIC); + +FltkFont::FontFamily::FontFamily (Fl_Font fontNormal, Fl_Font fontBold, + Fl_Font fontItalic, Fl_Font fontBoldItalic) +{ + font[0] = fontNormal; + font[1] = fontBold; + font[2] = fontItalic; + font[3] = fontBoldItalic; +} + +void FltkFont::FontFamily::set (Fl_Font f, int attrs) +{ + int idx = 0; + if (attrs & FL_BOLD) + idx += 1; + if (attrs & FL_ITALIC) + idx += 2; + font[idx] = f; +} + +Fl_Font FltkFont::FontFamily::get (int attrs) +{ + int idx = 0; + if (attrs & FL_BOLD) + idx += 1; + if (attrs & FL_ITALIC) + idx += 2; + + // should the desired font style not exist, we + // return the normal font of the fontFamily + return font[idx] >= 0 ? font[idx] : font[0]; +} + + + FltkFont::FltkFont (core::style::FontAttrs *attrs) { + if (!systemFonts) + initSystemFonts (); + copyAttrs (attrs); int fa = 0; if (weight >= 500) - fa |= BOLD; + fa |= FL_BOLD; if (style != core::style::FONT_STYLE_NORMAL) - fa |= ITALIC; + fa |= FL_ITALIC; - font = ::fltk::font(name, fa); - if (font == NULL) { - /* - * If using xft, fltk::HELVETICA just means sans, fltk::COURIER - * means mono, and fltk::TIMES means serif. - */ - font = HELVETICA->plus (fa); - } + object::ConstString nameString (name); + FontFamily *family = systemFonts->get (&nameString); + if (!family) + family = &standardFontFamily; - setfont(font, size); - spaceWidth = misc::max(0, (int)getwidth(" ") + letterSpacing); - int xw, xh; - measure("x", xw, xh); - xHeight = xh; - ascent = (int)getascent(); - descent = (int)getdescent(); + font = family->get (fa); - /** - * \bug The code above does not seem to work, so this workaround. - */ - xHeight = ascent * 3 / 5; + fl_font(font, size); + /* WORKAROUND: fl_width(uint_t) is not working on non-xft X. + * Reported to FLTK as STR #2688 */ + spaceWidth = misc::max(0, (int)fl_width(" ") + letterSpacing); + int xx, xy, xw, xh; + fl_text_extents("x", xx, xy, xw, xh); + xHeight = xh; + descent = fl_descent(); + ascent = fl_height() - descent; } FltkFont::~FltkFont () @@ -85,10 +138,75 @@ FltkFont::~FltkFont () fontsTable->remove (this); } +static void strstrip(char *big, const char *little) +{ + if (strlen(big) >= strlen(little) && + strcasecmp(big + strlen(big) - strlen(little), little) == 0) + *(big + strlen(big) - strlen(little)) = '\0'; +} + +void FltkFont::initSystemFonts () +{ + systemFonts = new container::typed::HashTable + <lout::object::ConstString, FontFamily> (true, true); + + int k = Fl::set_fonts ("-*-iso10646-1"); + for (int i = 0; i < k; i++) { + int t; + char *name = strdup (Fl::get_font_name ((Fl_Font) i, &t)); + + // normalize font family names (strip off "bold", "italic") + if (t & FL_ITALIC) + strstrip(name, " italic"); + if (t & FL_BOLD) + strstrip(name, " bold"); + + _MSG("Found font: %s%s%s\n", name, t & FL_BOLD ? " bold" : "", + t & FL_ITALIC ? " italic" : ""); + + object::String *familyName = new object::String(name); + free (name); + FontFamily *family = systemFonts->get (familyName); + + if (family) { + family->set ((Fl_Font) i, t); + delete familyName; + } else { + // set first font of family also as normal font in case there + // is no normal (non-bold, non-italic) font + family = new FontFamily ((Fl_Font) i, -1, -1, -1); + family->set ((Fl_Font) i, t); + systemFonts->put (familyName, family); + } + } +} + +bool +FltkFont::fontExists (const char *name) +{ + if (!systemFonts) + initSystemFonts (); + object::ConstString familyName (name); + return systemFonts->get (&familyName) != NULL; +} + +Fl_Font +FltkFont::get (const char *name, int attrs) +{ + if (!systemFonts) + initSystemFonts (); + object::ConstString familyName (name); + FontFamily *family = systemFonts->get (&familyName); + if (family) + return family->get (attrs); + else + return FL_HELVETICA; +} + bool FltkPlatform::fontExists (const char *name) { - return ::fltk::font(name) != NULL; + return FltkFont::fontExists (name); } FltkFont* @@ -114,26 +232,14 @@ FltkColor::FltkColor (int color): Color (color) { this->color = color; - /* - * fltk/setcolor.cxx: - * "A Color of zero (fltk::NO_COLOR) will draw black but is - * ambiguous. It is returned as an error value or to indicate portions - * of a Style that should be inherited, and it is also used as the - * default label color for everything so that changing color zero can - * be used by the -fg switch. You should use fltk::BLACK (56) to get - * black." - * - * i.e., zero only works sometimes. - */ - if (!(colors[SHADING_NORMAL] = shadeColor (color, SHADING_NORMAL) << 8)) - colors[SHADING_NORMAL] = ::fltk::BLACK; + colors[SHADING_NORMAL] = FL_BLACK; if (!(colors[SHADING_INVERSE] = shadeColor (color, SHADING_INVERSE) << 8)) - colors[SHADING_INVERSE] = ::fltk::BLACK; + colors[SHADING_INVERSE] = FL_BLACK; if (!(colors[SHADING_DARK] = shadeColor (color, SHADING_DARK) << 8)) - colors[SHADING_DARK] = ::fltk::BLACK; + colors[SHADING_DARK] = FL_BLACK; if (!(colors[SHADING_LIGHT] = shadeColor (color, SHADING_LIGHT) << 8)) - colors[SHADING_LIGHT] = ::fltk::BLACK; + colors[SHADING_LIGHT] = FL_BLACK; } FltkColor::~FltkColor () @@ -156,35 +262,12 @@ FltkColor * FltkColor::create (int col) FltkTooltip::FltkTooltip (const char *text) : Tooltip(text) { - shown = false; - - if (!text || !strpbrk(text, "&@")) { - escaped_str = NULL; - } else { - /* - * WORKAROUND: ::fltk::Tooltip::tooltip_timeout() makes instance_ - * if necessary, and immediately uses it. This means that we can't - * get our hands on it to set RAW_LABEL until after it has been shown - * once. So let's escape the special characters ourselves. - */ - const char *src = text; - char *dest = escaped_str = (char *) malloc(strlen(text) * 2 + 1); - - while (*src) { - if (*src == '&' || *src == '@') - *dest++ = *src; - *dest++ = *src++; - } - *dest = '\0'; - } } FltkTooltip::~FltkTooltip () { - if (shown) - ::fltk::Tooltip::exit(); - if (escaped_str) - free(escaped_str); + if (in_tooltip || req_tooltip) + cancel(); /* cancel tooltip window */ } FltkTooltip *FltkTooltip::create (const char *text) @@ -192,40 +275,115 @@ FltkTooltip *FltkTooltip::create (const char *text) return new FltkTooltip(text); } +/* + * Tooltip callback: used to delay it a bit + * INVARIANT: Only one instance of this function is requested. + */ +static void tooltip_tcb(void *data) +{ + req_tooltip = 2; + ((FltkTooltip *)data)->onEnter(); + req_tooltip = 0; +} + void FltkTooltip::onEnter() { - fltk::Widget *widget = fltk::belowmouse(); + _MSG("FltkTooltip::onEnter\n"); + if (!str || !*str) + return; + if (req_tooltip == 0) { + Fl::remove_timeout(tooltip_tcb); + Fl::add_timeout(1.0, tooltip_tcb, this); + req_tooltip = 1; + return; + } - ::fltk::Tooltip::enter(widget, *((fltk::Rectangle *)widget), - escaped_str ? escaped_str : str); - shown = true; + if (!tt_window) { + tt_window = new Fl_Menu_Window(0,0,100,24); + tt_window->set_override(); + tt_window->box(FL_NO_BOX); + Fl_Box *b = new Fl_Box(0,0,100,24); + b->box(FL_BORDER_BOX); + b->color(fl_color_cube(FL_NUM_RED-1, FL_NUM_GREEN-1, FL_NUM_BLUE-2)); + b->labelcolor(FL_BLACK); + b->labelfont(FL_HELVETICA); + b->labelsize(14); + b->align(FL_ALIGN_WRAP|FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + tt_window->resizable(b); + tt_window->end(); + } + + /* prepare tooltip window */ + int x, y; + Fl_Box *box = (Fl_Box*)tt_window->child(0); + box->label(str); + Fl::get_mouse(x,y); y += 6; + /* calculate window size */ + int ww, hh; + ww = 800; // max width; + box->measure_label(ww, hh); + ww += 6 + 2 * Fl::box_dx(box->box()); + hh += 6 + 2 * Fl::box_dy(box->box()); + tt_window->resize(x,y,ww,hh); + tt_window->show(); + in_tooltip = 1; } +/* + * Leaving the widget cancels the tooltip + */ void FltkTooltip::onLeave() { - ::fltk::Tooltip::exit(); - shown = false; + _MSG(" FltkTooltip::onLeave in_tooltip=%d\n", in_tooltip); + cancel(); +} + +void FltkPlatform::cancelTooltip() +{ + FltkTooltip::cancel(); +} + +/* + * Remove a shown tooltip or cancel a pending one + */ +void FltkTooltip::cancel() +{ + if (req_tooltip) { + Fl::remove_timeout(tooltip_tcb); + req_tooltip = 0; + } + if (!in_tooltip) return; + in_tooltip = 0; + tt_window->hide(); + + /* WORKAROUND: (Black magic here) + * Hiding a tooltip with the keyboard or mousewheel doesn't work. + * The code below "fixes" the problem */ + Fl_Widget *widget = Fl::belowmouse(); + if (widget && widget->window()) { + widget->window()->damage(FL_DAMAGE_EXPOSE,0,0,1,1); + } } void FltkTooltip::onMotion() { } -void FltkView::addFltkWidget (::fltk::Widget *widget, +void FltkView::addFltkWidget (Fl_Widget *widget, core::Allocation *allocation) { } -void FltkView::removeFltkWidget (::fltk::Widget *widget) +void FltkView::removeFltkWidget (Fl_Widget *widget) { } -void FltkView::allocateFltkWidget (::fltk::Widget *widget, +void FltkView::allocateFltkWidget (Fl_Widget *widget, core::Allocation *allocation) { } -void FltkView::drawFltkWidget (::fltk::Widget *widget, core::Rectangle *area) +void FltkView::drawFltkWidget (Fl_Widget *widget, core::Rectangle *area) { } @@ -310,7 +468,7 @@ FltkPlatform::FltkPlatform () FltkPlatform::~FltkPlatform () { if (idleFuncRunning) - remove_idle (generalStaticIdle, (void*)this); + Fl::remove_idle (generalStaticIdle, (void*)this); delete idleQueue; delete resources; } @@ -354,32 +512,32 @@ int FltkPlatform::textWidth (core::style::Font *font, const char *text, int len) { char chbuf[4]; - wchar_t wc, wcu; + int c, cu; int width = 0; FltkFont *ff = (FltkFont*) font; int curr = 0, next = 0, nb; - if (font->fontVariant == 1) { + if (font->fontVariant == core::style::FONT_VARIANT_SMALL_CAPS) { int sc_fontsize = lout::misc::roundInt(ff->size * 0.78); for (curr = 0; next < len; curr = next) { next = nextGlyph(text, curr); - wc = utf8decode(text + curr, text + next, &nb); - if ((wcu = towupper(wc)) == wc) { + c = fl_utf8decode(text + curr, text + next, &nb); + if ((cu = fl_toupper(c)) == c) { /* already uppercase, just draw the character */ - setfont(ff->font, ff->size); + fl_font(ff->font, ff->size); width += font->letterSpacing; - width += (int)getwidth(text + curr, next - curr); + width += (int)fl_width(text + curr, next - curr); } else { /* make utf8 string for converted char */ - nb = utf8encode(wcu, chbuf); - setfont(ff->font, sc_fontsize); + nb = fl_utf8encode(cu, chbuf); + fl_font(ff->font, sc_fontsize); width += font->letterSpacing; - width += (int)getwidth(chbuf, nb); + width += (int)fl_width(chbuf, nb); } } } else { - setfont (ff->font, ff->size); - width = (int) getwidth (text, len); + fl_font (ff->font, ff->size); + width = (int) fl_width (text, len); if (font->letterSpacing) { int curr = 0, next = 0; @@ -397,22 +555,28 @@ int FltkPlatform::textWidth (core::style::Font *font, const char *text, int FltkPlatform::nextGlyph (const char *text, int idx) { - return utf8fwd (&text[idx + 1], text, &text[strlen (text)]) - text; + return fl_utf8fwd (&text[idx + 1], text, &text[strlen (text)]) - text; } int FltkPlatform::prevGlyph (const char *text, int idx) { - return utf8back (&text[idx - 1], text, &text[strlen (text)]) - text; + return fl_utf8back (&text[idx - 1], text, &text[strlen (text)]) - text; } float FltkPlatform::dpiX () { - return ::fltk::Monitor::all ().dpi_x (); + float horizontal, vertical; + + Fl::screen_dpi(horizontal, vertical); + return horizontal; } float FltkPlatform::dpiY () { - return ::fltk::Monitor::all ().dpi_y (); + float horizontal, vertical; + + Fl::screen_dpi(horizontal, vertical); + return vertical; } void FltkPlatform::generalStaticIdle (void *data) @@ -435,7 +599,7 @@ void FltkPlatform::generalIdle () if (idleQueue->isEmpty()) { idleFuncRunning = false; - remove_idle (generalStaticIdle, (void*)this); + Fl::remove_idle (generalStaticIdle, (void*)this); } } @@ -449,7 +613,7 @@ int FltkPlatform::addIdle (void (core::Layout::*func) ()) * idle function, the passed idle function is put into a queue. */ if (!idleFuncRunning) { - add_idle (generalStaticIdle, (void*)this); + Fl::add_idle (generalStaticIdle, (void*)this); idleFuncRunning = true; } @@ -478,7 +642,7 @@ void FltkPlatform::removeIdle (int idleId) } if (idleFuncRunning && idleQueue->isEmpty()) - remove_idle (generalStaticIdle, (void*)this); + Fl::remove_idle (generalStaticIdle, (void*)this); } core::style::Font *FltkPlatform::createFont (core::style::FontAttrs @@ -500,7 +664,7 @@ core::style::Tooltip *FltkPlatform::createTooltip (const char *text) void FltkPlatform::copySelection(const char *text) { - fltk::copy(text, strlen(text), false); + Fl::copy(text, strlen(text), 0); } core::Imgbuf *FltkPlatform::createImgbuf (core::Imgbuf::Type type, diff --git a/dw/fltkplatform.hh b/dw/fltkplatform.hh index 7a708938..db4bc794 100644 --- a/dw/fltkplatform.hh +++ b/dw/fltkplatform.hh @@ -5,8 +5,6 @@ # error Do not include this file directly, use "fltkcore.hh" instead. #endif -#include <fltk/Font.h> - namespace dw { /** @@ -16,16 +14,33 @@ namespace fltk { class FltkFont: public core::style::Font { + class FontFamily: public lout::object::Object { + Fl_Font font[4]; + public: + FontFamily (Fl_Font fontNormal, Fl_Font fontBold, + Fl_Font fontItalic, Fl_Font fontBoldItalic); + void set (Fl_Font, int attrs); + Fl_Font get (int attrs); + }; + + static FontFamily standardFontFamily; + + static lout::container::typed::HashTable <lout::object::ConstString, + FontFamily> *systemFonts; static lout::container::typed::HashTable <dw::core::style::FontAttrs, FltkFont> *fontsTable; FltkFont (core::style::FontAttrs *attrs); ~FltkFont (); + static void initSystemFonts (); + public: - ::fltk::Font *font; + Fl_Font font; static FltkFont *create (core::style::FontAttrs *attrs); + static bool fontExists (const char *name); + static Fl_Font get (const char *name, int attrs); }; @@ -48,10 +63,9 @@ class FltkTooltip: public core::style::Tooltip private: FltkTooltip (const char *text); ~FltkTooltip (); - bool shown; - char *escaped_str; /* fltk WORKAROUND */ public: static FltkTooltip *create(const char *text); + static void cancel(); void onEnter(); void onLeave(); void onMotion(); @@ -66,12 +80,12 @@ class FltkView: public core::View public: virtual bool usesFltkWidgets () = 0; - virtual void addFltkWidget (::fltk::Widget *widget, + virtual void addFltkWidget (Fl_Widget *widget, core::Allocation *allocation); - virtual void removeFltkWidget (::fltk::Widget *widget); - virtual void allocateFltkWidget (::fltk::Widget *widget, + virtual void removeFltkWidget (Fl_Widget *widget); + virtual void allocateFltkWidget (Fl_Widget *widget, core::Allocation *allocation); - virtual void drawFltkWidget (::fltk::Widget *widget, core::Rectangle *area); + virtual void drawFltkWidget (Fl_Widget *widget, core::Rectangle *area); }; @@ -152,6 +166,7 @@ public: bool fontExists (const char *name); core::style::Color *createColor (int color); core::style::Tooltip *createTooltip (const char *text); + void cancelTooltip(); core::Imgbuf *createImgbuf (core::Imgbuf::Type type, int width, int height); diff --git a/dw/fltkpreview.cc b/dw/fltkpreview.cc index 7096420f..ecb96f22 100644 --- a/dw/fltkpreview.cc +++ b/dw/fltkpreview.cc @@ -22,15 +22,13 @@ #include "fltkpreview.hh" #include "fltkmisc.hh" -#include <fltk/events.h> -#include <fltk/xbmImage.h> -#include <fltk/draw.h> +#include <FL/Fl.H> +#include <FL/Fl_Bitmap.H> +#include <FL/fl_draw.H> #include <stdio.h> #include "preview.xbm" -using namespace ::fltk; - namespace dw { namespace fltk { @@ -126,7 +124,7 @@ void FltkPreview::drawText (core::style::Font *font, * else that measures text). */ FltkFont *ff = (FltkFont*)font; - setfont(ff->font, translateCanvasXToViewX (ff->size)); + Fl::set_font(ff->font, translateCanvasXToViewX (ff->size)); #if 0 /** * \todo Normally, this should already be known, maybe it @@ -144,9 +142,16 @@ void FltkPreview::drawText (core::style::Font *font, setcolor(((FltkColor*)color)->colors[shading]); fillrect (rect); #endif - setcolor(((FltkColor*)color)->colors[shading]); - drawtext(text, len, - translateCanvasXToViewX (x), translateCanvasYToViewY (y)); + fl_color(((FltkColor*)color)->colors[shading]); + fl_draw(text, len, translateCanvasXToViewX (x), translateCanvasYToViewY(y)); +} + +void FltkPreview::drawSimpleWrappedText (core::style::Font *font, + core::style::Color *color, + core::style::Color::Shading shading, + int x, int y, int w, int h, + const char *text) +{ } void FltkPreview::drawImage (core::Imgbuf *imgbuf, int xRoot, int yRoot, @@ -159,7 +164,7 @@ bool FltkPreview::usesFltkWidgets () return false; } -void FltkPreview::drawFltkWidget (::fltk::Widget *widget, +void FltkPreview::drawFltkWidget (Fl_Widget *widget, core::Rectangle *area) { } @@ -167,9 +172,9 @@ void FltkPreview::drawFltkWidget (::fltk::Widget *widget, // ---------------------------------------------------------------------- FltkPreviewWindow::FltkPreviewWindow (dw::core::Layout *layout): - MenuWindow (1, 1) + Fl_Menu_Window (1, 1) { - box (EMBOSSED_BOX); + box (FL_EMBOSSED_BOX); begin (); preview = new FltkPreview (BORDER_WIDTH, BORDER_WIDTH, 1, 1, layout); @@ -205,7 +210,7 @@ void FltkPreviewWindow::reallocate () height = preview->canvasHeight * maxWidth / preview->canvasWidth; } - get_mouse(mx, my); + Fl::get_mouse(mx, my); posX = mx - preview->translateCanvasXToViewX (preview->scrollX + preview->scrollWidth / 2); @@ -237,13 +242,12 @@ void FltkPreviewWindow::reallocate () resize (posX, posY, width, height); - preview->w (w () - 2 * BORDER_WIDTH); - preview->h (h () - 2 * BORDER_WIDTH); + preview->size(w () - 2 * BORDER_WIDTH, h () - 2 * BORDER_WIDTH); } void FltkPreviewWindow::hideWindow () { - Window::hide (); + Fl_Window::hide (); } void FltkPreviewWindow::scrollTo (int mouseX, int mouseY) @@ -263,9 +267,9 @@ void FltkPreviewWindow::scrollTo (int mouseX, int mouseY) FltkPreviewButton::FltkPreviewButton (int x, int y, int w, int h, dw::core::Layout *layout, const char *label): - Button (x, y, w, h, label) + Fl_Button (x, y, w, h, label) { - image (new xbmImage (preview_bits, preview_width, preview_height)); + image (new Fl_Bitmap (preview_bits, preview_width, preview_height)); window = new FltkPreviewWindow (layout); } @@ -278,23 +282,23 @@ int FltkPreviewButton::handle (int event) /** \bug Some parts are missing. */ switch (event) { - case PUSH: + case FL_PUSH: window->showWindow (); - return Button::handle (event); + return Fl_Button::handle (event); - case DRAG: + case FL_DRAG: if (window->visible ()) { - window->scrollTo (event_x_root (), event_y_root ()); + window->scrollTo (Fl::event_x_root (), Fl::event_y_root ()); return 1; } - return Button::handle (event); + return Fl_Button::handle (event); - case RELEASE: + case FL_RELEASE: window->hideWindow (); - return Button::handle (event); + return Fl_Button::handle (event); default: - return Button::handle (event); + return Fl_Button::handle (event); } } diff --git a/dw/fltkpreview.hh b/dw/fltkpreview.hh index 13db2811..2382b861 100644 --- a/dw/fltkpreview.hh +++ b/dw/fltkpreview.hh @@ -1,8 +1,8 @@ #ifndef __FlTKPREVIEW_HH__ #define __FlTKPREVIEW_HH__ -#include <fltk/Button.h> -#include <fltk/MenuWindow.h> +#include <FL/Fl_Button.H> +#include <FL/Fl_Menu_Window.H> #include "fltkviewbase.hh" namespace dw { @@ -42,15 +42,20 @@ public: core::style::Color *color, core::style::Color::Shading shading, int x, int y, const char *text, int len); + void drawSimpleWrappedText (core::style::Font *font, + core::style::Color *color, + core::style::Color::Shading shading, + int x, int y, int w, int h, + const char *text); void drawImage (core::Imgbuf *imgbuf, int xRoot, int yRoot, int x, int y, int width, int height); bool usesFltkWidgets (); - void drawFltkWidget (::fltk::Widget *widget, core::Rectangle *area); + void drawFltkWidget (Fl_Widget *widget, core::Rectangle *area); }; -class FltkPreviewWindow: public ::fltk::MenuWindow +class FltkPreviewWindow: public Fl_Menu_Window { private: enum { BORDER_WIDTH = 2 }; @@ -71,7 +76,7 @@ public: }; -class FltkPreviewButton: public ::fltk::Button +class FltkPreviewButton: public Fl_Button { private: FltkPreviewWindow *window; diff --git a/dw/fltkui.cc b/dw/fltkui.cc index ff80e14c..c0c8ff42 100644 --- a/dw/fltkui.cc +++ b/dw/fltkui.cc @@ -25,21 +25,57 @@ #include "../lout/msg.h" #include "../lout/misc.hh" +#include <FL/Fl.H> +#include <FL/fl_draw.H> +#include <FL/Fl_Input.H> +#include <FL/Fl_Text_Editor.H> +#include <FL/Fl_Check_Button.H> +#include <FL/Fl_Round_Button.H> +#include <FL/Fl_Choice.H> +#include <FL/Fl_Tree.H> + #include <stdio.h> -#include <fltk/Widget.h> -#include <fltk/Group.h> -#include <fltk/Input.h> -#include <fltk/TextEditor.h> -#include <fltk/RadioButton.h> -#include <fltk/CheckButton.h> -#include <fltk/Choice.h> -#include <fltk/Browser.h> -#include <fltk/Font.h> -#include <fltk/draw.h> -#include <fltk/Symbol.h> -#include <fltk/Item.h> -#include <fltk/ItemGroup.h> -#include <fltk/events.h> + +//---------------------------------------------------------------------------- +/* + * Local sub classes + */ + +/* + * Used to enable CTRL+{a,e,d,k} in form inputs (for start,end,del,cut) + */ +class CustInput2 : public Fl_Input { +public: + CustInput2 (int x, int y, int w, int h, const char* l=0) : + Fl_Input(x,y,w,h,l) {}; + int handle(int e); +}; + +int CustInput2::handle(int e) +{ + int k = Fl::event_key(); + + _MSG("CustInput2::handle event=%d\n", e); + + // We're only interested in some flags + unsigned modifier = Fl::event_state() & (FL_SHIFT | FL_CTRL | FL_ALT); + + if (e == FL_KEYBOARD && modifier == FL_CTRL) { + if (k == 'a' || k == 'e') { + position(k == 'a' ? 0 : size()); + return 1; + } else if (k == 'k') { + cut(position(), size()); + return 1; + } else if (k == 'd') { + cut(position(), position()+1); + return 1; + } + } + return Fl_Input::handle(e); +} + +//---------------------------------------------------------------------------- namespace dw { namespace fltk { @@ -139,14 +175,12 @@ void FltkResource::setStyle (core::style::Style *style) setWidgetStyle (widget, style); } -void FltkResource::setWidgetStyle (::fltk::Widget *widget, +void FltkResource::setWidgetStyle (Fl_Widget *widget, core::style::Style *style) { FltkFont *font = (FltkFont*)style->font; widget->labelsize (font->size); widget->labelfont (font->font); - widget->textsize (font->size); - widget->textfont (font->font); FltkColor *bg = (FltkColor*)style->backgroundColor; if (bg) { @@ -155,21 +189,13 @@ void FltkResource::setWidgetStyle (::fltk::Widget *widget, if (style->color) { int style_fg = ((FltkColor*)style->color)->colors [FltkColor::SHADING_NORMAL]; - ::fltk::Color fg = ::fltk::contrast(style_fg, normal_bg); + Fl_Color fg = fl_contrast(style_fg, normal_bg); widget->labelcolor(fg); - widget->textcolor(fg); widget->selection_color(fg); } widget->color(normal_bg); - widget->buttoncolor(normal_bg); - widget->selection_textcolor(normal_bg); - if (widget->type() != ::fltk::Widget::RADIO && - widget->type() != ::fltk::Widget::TOGGLE) { - /* it looks awful to highlight the buttons */ - widget->highlight_color(bg->colors[FltkColor::SHADING_LIGHT]); - } } } @@ -250,19 +276,17 @@ FltkLabelButtonResource::FltkLabelButtonResource (FltkPlatform *platform, FltkLabelButtonResource::~FltkLabelButtonResource () { - delete label; + free((char *)label); } -::fltk::Widget *FltkLabelButtonResource::createNewWidget (core::Allocation - *allocation) +Fl_Widget *FltkLabelButtonResource::createNewWidget (core::Allocation + *allocation) { - ::fltk::Button *button = - new ::fltk::Button (allocation->x, allocation->y, allocation->width, - allocation->ascent + allocation->descent, - label); - button->set_flag (::fltk::RAW_LABEL); + Fl_Button *button = + new Fl_Button (allocation->x, allocation->y, allocation->width, + allocation->ascent + allocation->descent, label); button->callback (widgetCallback, this); - button->when (::fltk::WHEN_RELEASE); + button->when (FL_WHEN_RELEASE); return button; } @@ -270,9 +294,9 @@ void FltkLabelButtonResource::sizeRequest (core::Requisition *requisition) { if (style) { FltkFont *font = (FltkFont*)style->font; - ::fltk::setfont(font->font,font->size); + fl_font(font->font,font->size); requisition->width = - (int)::fltk::getwidth (label, strlen (label)) + (int)fl_width (label, strlen (label)) + 2 * RELIEF_X_THICKNESS; requisition->ascent = font->ascent + RELIEF_Y_THICKNESS; requisition->descent = font->descent + RELIEF_Y_THICKNESS; @@ -290,35 +314,32 @@ void FltkLabelButtonResource::sizeRequest (core::Requisition *requisition) */ static core::ButtonState getDwButtonState () { - int s1 = ::fltk::event_state (); + int s1 = Fl::event_state (); int s2 = (core::ButtonState)0; - if (s1 & ::fltk::SHIFT) s2 |= core::SHIFT_MASK; - if (s1 & ::fltk::CTRL) s2 |= core::CONTROL_MASK; - if (s1 & ::fltk::ALT) s2 |= core::META_MASK; - if (s1 & ::fltk::BUTTON1) s2 |= core::BUTTON1_MASK; - if (s1 & ::fltk::BUTTON2) s2 |= core::BUTTON2_MASK; - if (s1 & ::fltk::BUTTON3) s2 |= core::BUTTON3_MASK; + if (s1 & FL_SHIFT) s2 |= core::SHIFT_MASK; + if (s1 & FL_CTRL) s2 |= core::CONTROL_MASK; + if (s1 & FL_ALT) s2 |= core::META_MASK; + if (s1 & FL_BUTTON1) s2 |= core::BUTTON1_MASK; + if (s1 & FL_BUTTON2) s2 |= core::BUTTON2_MASK; + if (s1 & FL_BUTTON3) s2 |= core::BUTTON3_MASK; return (core::ButtonState)s2; } static void setButtonEvent(dw::core::EventButton *event) { - event->xCanvas = ::fltk::event_x(); - event->yCanvas = ::fltk::event_y(); + event->xCanvas = Fl::event_x(); + event->yCanvas = Fl::event_y(); event->state = getDwButtonState(); - event->button = ::fltk::event_button(); - event->numPressed = ::fltk::event_clicks() + 1; + event->button = Fl::event_button(); + event->numPressed = Fl::event_clicks() + 1; } -void FltkLabelButtonResource::widgetCallback (::fltk::Widget *widget, +void FltkLabelButtonResource::widgetCallback (Fl_Widget *widget, void *data) { - if ((widget->when () & ::fltk::WHEN_RELEASE) && - ((::fltk::event_key() == ::fltk::ReturnKey) || - (::fltk::event_button() == ::fltk::LeftButton || - ::fltk::event_button() == ::fltk::MiddleButton))) { + if (!Fl::event_button3()) { FltkLabelButtonResource *lbr = (FltkLabelButtonResource*) data; dw::core::EventButton event; setButtonEvent(&event); @@ -334,7 +355,7 @@ const char *FltkLabelButtonResource::getLabel () void FltkLabelButtonResource::setLabel (const char *label) { - delete this->label; + free((char *)this->label); this->label = strdup (label); widget->label (this->label); @@ -358,22 +379,17 @@ FltkComplexButtonResource::~FltkComplexButtonResource () { } -void FltkComplexButtonResource::widgetCallback (::fltk::Widget *widget, +void FltkComplexButtonResource::widgetCallback (Fl_Widget *widget, void *data) { FltkComplexButtonResource *res = (FltkComplexButtonResource*)data; - if (widget->when() == ::fltk::WHEN_RELEASE && - ((::fltk::event_key() == ::fltk::ReturnKey) || - (::fltk::event_button() == ::fltk::LeftButton || - ::fltk::event_button() == ::fltk::MiddleButton))) { - res->click_x = ::fltk::event_x(); - res->click_y = ::fltk::event_y(); + if (!Fl::event_button3()) { + res->click_x = Fl::event_x(); + res->click_y = Fl::event_y(); dw::core::EventButton event; setButtonEvent(&event); res->emitClicked(&event); - } else { - ((FltkViewBase*)res->flatView)->handle(::fltk::event()); } } @@ -423,16 +439,16 @@ int FltkComplexButtonResource::reliefYThickness () } -::fltk::Widget *FltkComplexButtonResource::createNewWidget (core::Allocation +Fl_Widget *FltkComplexButtonResource::createNewWidget (core::Allocation *allocation) { ComplexButton *button = new ComplexButton (allocation->x, allocation->y, allocation->width, allocation->ascent + allocation->descent); button->callback (widgetCallback, this); - button->when (::fltk::WHEN_RELEASE); + button->when (FL_WHEN_RELEASE); if (!relief) - button->box(::fltk::FLAT_BOX); + button->box(FL_FLAT_BOX); flatView = new FltkFlatView (allocation->x + reliefXThickness (), allocation->y + reliefYThickness (), @@ -455,6 +471,7 @@ FltkEntryResource::FltkEntryResource (FltkPlatform *platform, int maxLength, this->maxLength = maxLength; this->password = password; this->label = label ? strdup(label) : NULL; + this->label_w = 0; initText = NULL; editable = false; @@ -465,25 +482,25 @@ FltkEntryResource::FltkEntryResource (FltkPlatform *platform, int maxLength, FltkEntryResource::~FltkEntryResource () { if (initText) - delete initText; + free((char *)initText); if (label) - delete label; + free(label); } -::fltk::Widget *FltkEntryResource::createNewWidget (core::Allocation +Fl_Widget *FltkEntryResource::createNewWidget (core::Allocation *allocation) { - ::fltk::Input *input = - new ::fltk::Input (allocation->x, allocation->y, allocation->width, - allocation->ascent + allocation->descent); + Fl_Input *input = + new CustInput2(allocation->x, allocation->y, allocation->width, + allocation->ascent + allocation->descent); if (password) - input->type(::fltk::Input::SECRET); + input->type(FL_SECRET_INPUT); input->callback (widgetCallback, this); - input->when (::fltk::WHEN_ENTER_KEY_ALWAYS); + input->when (FL_WHEN_ENTER_KEY_ALWAYS); if (label) { input->label(label); - input->set_flag(::fltk::ALIGN_INSIDE_LEFT); + input->align(FL_ALIGN_LEFT); } if (initText) input->value (initText); @@ -491,6 +508,26 @@ FltkEntryResource::~FltkEntryResource () return input; } +void FltkEntryResource::setWidgetStyle (Fl_Widget *widget, + core::style::Style *style) +{ + Fl_Input *in = (Fl_Input *)widget; + + FltkResource::setWidgetStyle(widget, style); + + in->textcolor(widget->labelcolor()); + in->cursor_color(in->textcolor()); + in->textsize(in->labelsize()); + in->textfont(in->labelfont()); + + if (label) { + int h; + label_w = 0; + widget->measure_label(label_w, h); + label_w += RELIEF_X_THICKNESS; + } +} + void FltkEntryResource::setDisplayed(bool displayed) { FltkResource::setDisplayed(displayed); @@ -501,11 +538,13 @@ void FltkEntryResource::sizeRequest (core::Requisition *requisition) { if (displayed() && style) { FltkFont *font = (FltkFont*)style->font; - ::fltk::setfont(font->font,font->size); + fl_font(font->font,font->size); + /* WORKAROUND: fl_width(uint_t) is not working on non-xft X. + * Reported to FLTK as STR #2688 */ requisition->width = - (int)::fltk::getwidth ("n", 1) + (int)fl_width ("n") * (maxLength == UNLIMITED_MAX_LENGTH ? 10 : maxLength) - + 2 * RELIEF_X_THICKNESS; + + label_w + (2 * RELIEF_X_THICKNESS); requisition->ascent = font->ascent + RELIEF_Y_THICKNESS; requisition->descent = font->descent + RELIEF_Y_THICKNESS; } else { @@ -515,33 +554,38 @@ void FltkEntryResource::sizeRequest (core::Requisition *requisition) } } -void FltkEntryResource::widgetCallback (::fltk::Widget *widget, - void *data) +void FltkEntryResource::sizeAllocate (core::Allocation *allocation) { - /* The (::fltk::event_key() == ::fltk::ReturnKey) test - * is necessary because WHEN_ENTER_KEY also includes - * other events we're not interested in. For instance pressing - * The Back or Forward, buttons, or the first click on a rendered - * page. BUG: this must be investigated and reported to FLTK2 team - */ - _MSG("when = %d\n", widget->when ()); - if ((widget->when () & ::fltk::WHEN_ENTER_KEY_ALWAYS) && - (::fltk::event_key() == ::fltk::ReturnKey)) - ((FltkEntryResource*)data)->emitActivate (); + if (!label) { + FltkResource::sizeAllocate(allocation); + } else { + this->allocation = *allocation; + + /* push the Fl_Input over to the right of the label */ + core::Allocation a = this->allocation; + a.x += this->label_w; + a.width -= this->label_w; + view->allocateFltkWidget (widget, &a); + } +} + +void FltkEntryResource::widgetCallback (Fl_Widget *widget, void *data) +{ + ((FltkEntryResource*)data)->emitActivate (); } const char *FltkEntryResource::getText () { - return ((::fltk::Input*)widget)->value (); + return ((Fl_Input*)widget)->value (); } void FltkEntryResource::setText (const char *text) { if (initText) - delete initText; + free((char *)initText); initText = strdup (text); - ((::fltk::Input*)widget)->value (initText); + ((Fl_Input*)widget)->value (initText); } bool FltkEntryResource::isEditable () @@ -560,7 +604,8 @@ FltkMultiLineTextResource::FltkMultiLineTextResource (FltkPlatform *platform, int cols, int rows): FltkSpecificResource <dw::core::ui::MultiLineTextResource> (platform) { - buffer = new ::fltk::TextBuffer; + buffer = new Fl_Text_Buffer; + text_copy = NULL; editable = false; numCols = cols; @@ -582,29 +627,45 @@ FltkMultiLineTextResource::FltkMultiLineTextResource (FltkPlatform *platform, FltkMultiLineTextResource::~FltkMultiLineTextResource () { /* Free memory avoiding a double-free of text buffers */ - ((::fltk::TextEditor *) widget)->buffer (0); + ((Fl_Text_Editor *) widget)->buffer (0); delete buffer; + if (text_copy) + free(text_copy); } -::fltk::Widget *FltkMultiLineTextResource::createNewWidget (core::Allocation +Fl_Widget *FltkMultiLineTextResource::createNewWidget (core::Allocation *allocation) { - ::fltk::TextEditor *text = - new ::fltk::TextEditor (allocation->x, allocation->y, - allocation->width, - allocation->ascent + allocation->descent); + Fl_Text_Editor *text = + new Fl_Text_Editor (allocation->x, allocation->y, allocation->width, + allocation->ascent + allocation->descent); + text->wrap_mode(Fl_Text_Display::WRAP_AT_BOUNDS, 0); text->buffer (buffer); return text; } +void FltkMultiLineTextResource::setWidgetStyle (Fl_Widget *widget, + core::style::Style *style) +{ + Fl_Text_Editor *ed = (Fl_Text_Editor *)widget; + + FltkResource::setWidgetStyle(widget, style); + + ed->textcolor(widget->labelcolor()); + ed->cursor_color(ed->textcolor()); + ed->textsize(ed->labelsize()); + ed->textfont(ed->labelfont()); +} + void FltkMultiLineTextResource::sizeRequest (core::Requisition *requisition) { if (style) { FltkFont *font = (FltkFont*)style->font; - ::fltk::setfont(font->font,font->size); + fl_font(font->font,font->size); + /* WORKAROUND: fl_width(uint_t) is not working on non-xft X. + * Reported to FLTK as STR #2688 */ requisition->width = - (int)::fltk::getwidth ("n", 1) * numCols + - 2 * RELIEF_X_THICKNESS; + (int)fl_width ("n") * numCols + 2 * RELIEF_X_THICKNESS; requisition->ascent = RELIEF_Y_THICKNESS + font->ascent + (font->ascent + font->descent) * (numRows - 1); @@ -620,7 +681,13 @@ void FltkMultiLineTextResource::sizeRequest (core::Requisition *requisition) const char *FltkMultiLineTextResource::getText () { - return buffer->text (); + /* FLTK-1.3 insists upon returning a new copy of the buffer text, so + * we have to keep track of it. + */ + if (text_copy) + free(text_copy); + text_copy = buffer->text(); + return text_copy; } void FltkMultiLineTextResource::setText (const char *text) @@ -656,14 +723,23 @@ FltkToggleButtonResource<I>::~FltkToggleButtonResource () template <class I> -::fltk::Widget *FltkToggleButtonResource<I>::createNewWidget (core::Allocation +Fl_Widget *FltkToggleButtonResource<I>::createNewWidget (core::Allocation *allocation) { - ::fltk::Button *button = createNewButton (allocation); + Fl_Button *button = createNewButton (allocation); button->value (initActivated); return button; } +template <class I> +void FltkToggleButtonResource<I>::setWidgetStyle (Fl_Widget *widget, + core::style::Style *style) +{ + FltkResource::setWidgetStyle(widget, style); + + widget->selection_color(FL_BLACK); +} + template <class I> void FltkToggleButtonResource<I>::sizeRequest (core::Requisition *requisition) @@ -672,7 +748,7 @@ void FltkToggleButtonResource<I>::sizeRequest (core::Requisition *requisition) (this->FltkResource::style ? this->FltkResource::style->font : NULL); if (font) { - ::fltk::setfont(font->font, font->size); + fl_font(font->font, font->size); requisition->width = font->ascent + font->descent + 2*RELIEF_X_THICKNESS; requisition->ascent = font->ascent + RELIEF_Y_THICKNESS; requisition->descent = font->descent + RELIEF_Y_THICKNESS; @@ -687,7 +763,7 @@ void FltkToggleButtonResource<I>::sizeRequest (core::Requisition *requisition) template <class I> bool FltkToggleButtonResource<I>::FltkToggleButtonResource::isActivated () { - return ((::fltk::Button*)this->widget)->value (); + return ((Fl_Button*)this->widget)->value (); } @@ -695,7 +771,7 @@ template <class I> void FltkToggleButtonResource<I>::setActivated (bool activated) { initActivated = activated; - ((::fltk::Button*)this->widget)->value (initActivated); + ((Fl_Button*)this->widget)->value (initActivated); } // ---------------------------------------------------------------------- @@ -714,13 +790,12 @@ FltkCheckButtonResource::~FltkCheckButtonResource () } -::fltk::Button *FltkCheckButtonResource::createNewButton (core::Allocation +Fl_Button *FltkCheckButtonResource::createNewButton (core::Allocation *allocation) { - ::fltk::CheckButton *cb = - new ::fltk::CheckButton (allocation->x, allocation->y, allocation->width, - allocation->ascent + allocation->descent); - cb->set_flag (::fltk::RAW_LABEL); + Fl_Check_Button *cb = + new Fl_Check_Button (allocation->x, allocation->y, allocation->width, + allocation->ascent + allocation->descent); return cb; } @@ -798,10 +873,10 @@ dw::core::ui::RadioButtonResource::GroupIterator return group->groupIterator (); } -void FltkRadioButtonResource::widgetCallback (::fltk::Widget *widget, +void FltkRadioButtonResource::widgetCallback (Fl_Widget *widget, void *data) { - if (widget->when () & ::fltk::WHEN_CHANGED) + if (widget->when () & FL_WHEN_CHANGED) ((FltkRadioButtonResource*)data)->buttonClicked (); } @@ -814,11 +889,11 @@ void FltkRadioButtonResource::buttonClicked () } } -::fltk::Button *FltkRadioButtonResource::createNewButton (core::Allocation - *allocation) +Fl_Button *FltkRadioButtonResource::createNewButton (core::Allocation + *allocation) { /* - * Groups of fltk::RadioButton must be added to one fltk::Group, which is + * Groups of Fl_Radio_Button must be added to one Fl_Group, which is * not possible in this context. For this, we do the grouping ourself, * based on FltkRadioButtonResource::Group. * @@ -829,297 +904,191 @@ void FltkRadioButtonResource::buttonClicked () * (instead of creating a check button, and changing the style). */ - ::fltk::Button *button = - new ::fltk::RadioButton (allocation->x, allocation->y, - allocation->width, - allocation->ascent + allocation->descent); - button->set_flag (::fltk::RAW_LABEL); - button->when (::fltk::WHEN_CHANGED); + Fl_Button *button = + new Fl_Round_Button (allocation->x, allocation->y, allocation->width, + allocation->ascent + allocation->descent); + button->when (FL_WHEN_CHANGED); button->callback (widgetCallback, this); - button->type (::fltk::Button::TOGGLE); + button->type (FL_TOGGLE_BUTTON); return button; } // ---------------------------------------------------------------------- -template <class I> FltkSelectionResource<I>::Item::Item (Type type, - const char *name, - bool enabled, - bool selected) +template <class I> dw::core::Iterator * +FltkSelectionResource<I>::iterator (dw::core::Content::Type mask, bool atEnd) { - this->type = type; - this->name = name ? strdup (name) : NULL; - this->enabled = enabled; - initSelected = selected; + /** \bug Implementation. */ + return new core::EmptyIterator (this->getEmbed (), mask, atEnd); } -template <class I> FltkSelectionResource<I>::Item::~Item () -{ - if (name) - delete name; -} +// ---------------------------------------------------------------------- -template <class I> -::fltk::Item *FltkSelectionResource<I>::Item::createNewWidget (int index) +FltkOptionMenuResource::FltkOptionMenuResource (FltkPlatform *platform): + FltkSelectionResource <dw::core::ui::OptionMenuResource> (platform) { - ::fltk::Item *item = new ::fltk::Item (name); - item->set_flag (::fltk::RAW_LABEL); - item->user_data ((void *) index); - return item; -} + /* Fl_Menu_ does not like multiple menu items with the same label, and + * insert() treats some characters specially unless escaped, so let's + * do our own menu handling. + */ + itemsAllocated = 0x10; + menu = new Fl_Menu_Item[itemsAllocated]; + memset(menu, 0, itemsAllocated * sizeof(Fl_Menu_Item)); + itemsUsed = 1; // menu[0].text == NULL, which is an end-of-menu marker. + visibleItems = 0; -template <class I> -::fltk::ItemGroup * -FltkSelectionResource<I>::Item::createNewGroupWidget () -{ - ::fltk::ItemGroup *itemGroup = new ::fltk::ItemGroup (name); - itemGroup->set_flag (::fltk::RAW_LABEL); - itemGroup->user_data ((void *) -1L); - return itemGroup; + init (platform); } - -template <class I> -FltkSelectionResource<I>::WidgetStack::WidgetStack (::fltk::Menu *widget) +FltkOptionMenuResource::~FltkOptionMenuResource () { - this->widget = widget; - this->stack = new Stack <TypedPointer < ::fltk::Menu> > (true); + for (int i = 0; i < itemsUsed; i++) { + if (menu[i].text) + free((char *) menu[i].text); + } + delete[] menu; } -template <class I> FltkSelectionResource<I>::WidgetStack::~WidgetStack () +void FltkOptionMenuResource::setWidgetStyle (Fl_Widget *widget, + core::style::Style *style) { - delete stack; -} + Fl_Choice *ch = (Fl_Choice *)widget; + FltkResource::setWidgetStyle(widget, style); -template <class I> -FltkSelectionResource<I>::FltkSelectionResource (FltkPlatform *platform): - FltkSpecificResource<I> (platform) -{ - widgetStacks = new List <WidgetStack> (true); - allItems = new List <Item> (true); - items = new Vector <Item> (16, false); + ch->textcolor(widget->labelcolor()); + ch->textfont(ch->labelfont()); + ch->textsize(ch->labelsize()); } -template <class I> FltkSelectionResource<I>::~FltkSelectionResource () +Fl_Widget *FltkOptionMenuResource::createNewWidget (core::Allocation + *allocation) { - delete widgetStacks; - delete allItems; - delete items; + Fl_Choice *choice = + new Fl_Choice (allocation->x, allocation->y, + allocation->width, + allocation->ascent + allocation->descent); + choice->menu(menu); + return choice; } -template <class I> dw::core::Iterator * -FltkSelectionResource<I>::iterator (dw::core::Content::Type mask, bool atEnd) +void FltkOptionMenuResource::widgetCallback (Fl_Widget *widget, + void *data) { - /** \bug Implementation. */ - return new core::EmptyIterator (this->getEmbed (), mask, atEnd); } -template <class I> ::fltk::Widget * -FltkSelectionResource<I>::createNewWidget (core::Allocation *allocation) +int FltkOptionMenuResource::getMaxItemWidth() { - /** \todo Attributes (enabled, selected). */ - - ::fltk::Menu *menu = createNewMenu (allocation); - WidgetStack *widgetStack = new WidgetStack (menu); - widgetStack->stack->push (new TypedPointer < ::fltk::Menu> (menu)); - widgetStacks->append (widgetStack); - + int i, max = 0; - ::fltk::Menu *itemGroup; - ::fltk::Item *itemWidget; + for (i = 0; i < itemsUsed; i++) { + int width = 0; + const char *str = menu[i].text; - ::fltk::Group *currGroup = widgetStack->stack->getTop()->getTypedValue(); - - int index = 0; - for (Iterator <Item> it = allItems->iterator (); it.hasNext (); ) { - Item *item = it.getNext (); - switch (item->type) { - case Item::ITEM: - itemWidget = item->createNewWidget (index++); - currGroup->add (itemWidget); - break; - - case Item::START: - itemGroup = item->createNewGroupWidget (); - currGroup->add (itemGroup); - widgetStack->stack->push (new TypedPointer < ::fltk::Menu> (menu)); - currGroup = itemGroup; - break; - - case Item::END: - widgetStack->stack->pop (); - currGroup = widgetStack->stack->getTop()->getTypedValue(); - break; + if (str) { + width = fl_width(str); + if (width > max) + max = width; } } - - return menu; + return max; } -template <class I> -typename FltkSelectionResource<I>::Item * -FltkSelectionResource<I>::createNewItem (typename Item::Type type, - const char *name, - bool enabled, - bool selected) { - return new Item(type,name,enabled,selected); -} - -template <class I> void FltkSelectionResource<I>::addItem (const char *str, - bool enabled, - bool selected) -{ - int index = items->size (); - Item *item = createNewItem (Item::ITEM, str, enabled, selected); - items->put (item); - allItems->append (item); - - for (Iterator <WidgetStack> it = widgetStacks->iterator (); - it.hasNext(); ) { - WidgetStack *widgetStack = it.getNext (); - ::fltk::Item *itemWidget = item->createNewWidget (index); - widgetStack->stack->getTop()->getTypedValue()->add (itemWidget); - - if (!enabled) - itemWidget->deactivate (); - - if (selected) { - itemWidget->set_selected(); - if (setSelectedItems ()) { - // Handle multiple item selection. - int *pos = new int[widgetStack->stack->size ()]; - int i; - Iterator <TypedPointer < ::fltk::Menu> > it; - for (it = widgetStack->stack->iterator (), - i = widgetStack->stack->size () - 1; - it.hasNext (); - i--) { - TypedPointer < ::fltk::Menu> * p = it.getNext (); - pos[i] = p->getTypedValue()->children () - 1; - } - widgetStack->widget->set_item (pos, widgetStack->stack->size ()); - delete [] pos; - } - } +void FltkOptionMenuResource::sizeRequest (core::Requisition *requisition) +{ + if (style) { + FltkFont *font = (FltkFont*)style->font; + fl_font(font->font, font->size); + int maxItemWidth = getMaxItemWidth (); + requisition->ascent = font->ascent + RELIEF_Y_THICKNESS; + requisition->descent = font->descent + RELIEF_Y_THICKNESS; + requisition->width = maxItemWidth + + (requisition->ascent + requisition->descent) + + 2 * RELIEF_X_THICKNESS; + } else { + requisition->width = 1; + requisition->ascent = 1; + requisition->descent = 0; } } -template <class I> void FltkSelectionResource<I>::pushGroup (const char *name, - bool enabled) +void FltkOptionMenuResource::enlargeMenu () { - Item *item = createNewItem (Item::START, name, enabled); - allItems->append (item); + Fl_Choice *ch = (Fl_Choice *)widget; + int selected = ch->value(); + Fl_Menu_Item *newMenu; - for (Iterator <WidgetStack> it = widgetStacks->iterator (); - it.hasNext(); ) { - WidgetStack *widgetStack = it.getNext (); - ::fltk::ItemGroup *group = item->createNewGroupWidget (); - widgetStack->stack->getTop()->getTypedValue()->add (group); - widgetStack->stack->push (new TypedPointer < ::fltk::Menu> (group)); - if (!enabled) - group->deactivate (); - } + itemsAllocated += 0x10; + newMenu = new Fl_Menu_Item[itemsAllocated]; + memcpy(newMenu, menu, itemsUsed * sizeof(Fl_Menu_Item)); + memset(newMenu + itemsUsed, 0, 0x10 * sizeof(Fl_Menu_Item)); + delete[] menu; + menu = newMenu; + ch->menu(menu); + ch->value(selected); } -template <class I> void FltkSelectionResource<I>::popGroup () +Fl_Menu_Item *FltkOptionMenuResource::newItem() { - Item *item = createNewItem (Item::END); - allItems->append (item); + Fl_Menu_Item *item; - for (Iterator <WidgetStack> it = widgetStacks->iterator (); - it.hasNext(); ) { - WidgetStack *widgetStack = it.getNext (); - widgetStack->stack->pop (); - } -} + if (itemsUsed == itemsAllocated) + enlargeMenu(); -template <class I> int FltkSelectionResource<I>::getNumberOfItems () -{ - return items->size (); -} + item = menu + itemsUsed - 1; + itemsUsed++; -template <class I> const char *FltkSelectionResource<I>::getItem (int index) -{ - return items->get(index)->name; + return item; } -template <class I> int FltkSelectionResource<I>::getMaxStringWidth () +void FltkOptionMenuResource::addItem (const char *str, + bool enabled, bool selected) { - int width = 0, numberOfItems = getNumberOfItems (); - for (int i = 0; i < numberOfItems; i++) { - int len = (int)::fltk::getwidth (getItem(i)); - if (len > width) width = len; - } - return width; -} + Fl_Menu_Item *item = newItem(); -// ---------------------------------------------------------------------- + item->text = strdup(str); + item->argument(visibleItems++); -FltkOptionMenuResource::FltkOptionMenuResource (FltkPlatform *platform): - FltkSelectionResource <dw::core::ui::OptionMenuResource> (platform), - selection(-1) -{ - init (platform); + if (enabled == false) + item->flags = FL_MENU_INACTIVE; + + if (selected) + ((Fl_Choice *)widget)->value(item); + + queueResize (true); } -FltkOptionMenuResource::~FltkOptionMenuResource () +void FltkOptionMenuResource::pushGroup (const char *name, bool enabled) { -} + Fl_Menu_Item *item = newItem(); + item->text = strdup(name); + item->argument(visibleItems++); -::fltk::Menu *FltkOptionMenuResource::createNewMenu (core::Allocation - *allocation) -{ - ::fltk::Menu *menu = - new ::fltk::Choice (allocation->x, allocation->y, - allocation->width, - allocation->ascent + allocation->descent); - menu->set_flag (::fltk::RAW_LABEL); - menu->callback(widgetCallback,this); - return menu; -} + if (enabled == false) + item->flags = FL_MENU_INACTIVE; -void FltkOptionMenuResource::widgetCallback (::fltk::Widget *widget, - void *data) -{ - ((FltkOptionMenuResource *) data)->selection = - (long) (((::fltk::Menu *) widget)->item()->user_data()); -} + item->flags |= FL_SUBMENU; -void FltkOptionMenuResource::sizeRequest (core::Requisition *requisition) -{ - if (style) { - FltkFont *font = (FltkFont*)style->font; - ::fltk::setfont(font->font,font->size); - int maxStringWidth = getMaxStringWidth (); - requisition->ascent = font->ascent + RELIEF_Y_THICKNESS; - requisition->descent = font->descent + RELIEF_Y_THICKNESS; - requisition->width = maxStringWidth - + (requisition->ascent + requisition->descent) * 4 / 5 - + 2 * RELIEF_X_THICKNESS; - } else { - requisition->width = 1; - requisition->ascent = 1; - requisition->descent = 0; - } + queueResize (true); } -void FltkOptionMenuResource::addItem (const char *str, - bool enabled, bool selected) +void FltkOptionMenuResource::popGroup () { - FltkSelectionResource<dw::core::ui::OptionMenuResource>::addItem - (str,enabled,selected); - if (selected) - selection = (items->size ()) - 1; - + /* Item with NULL text field closes the submenu */ + newItem(); queueResize (true); } bool FltkOptionMenuResource::isSelected (int index) { - return index == selection; + return index == (long) ((Fl_Choice *)widget)->mvalue()->user_data(); +} + +int FltkOptionMenuResource::getNumberOfItems() +{ + return ((Fl_Choice*)widget)->size(); } // ---------------------------------------------------------------------- @@ -1140,70 +1109,133 @@ FltkListResource::~FltkListResource () } -::fltk::Menu *FltkListResource::createNewMenu (core::Allocation *allocation) +Fl_Widget *FltkListResource::createNewWidget (core::Allocation *allocation) { - ::fltk::Menu *menu = - new ::fltk::Browser (allocation->x, allocation->y, allocation->width, + Fl_Tree *tree = + new Fl_Tree (allocation->x, allocation->y, allocation->width, allocation->ascent + allocation->descent); - if (mode == SELECTION_MULTIPLE) - menu->type(::fltk::Browser::MULTI); - menu->set_flag (::fltk::RAW_LABEL); - menu->callback(widgetCallback,this); - menu->when(::fltk::WHEN_CHANGED); - return menu; + + tree->selectmode((mode == SELECTION_MULTIPLE) ? FL_TREE_SELECT_MULTI + : FL_TREE_SELECT_SINGLE); + tree->showroot(0); + tree->connectorstyle(FL_TREE_CONNECTOR_NONE); + tree->marginleft(-14); + tree->callback(widgetCallback,this); + tree->when(FL_WHEN_CHANGED); + + currParent = tree->root(); + return tree; } -void FltkListResource::widgetCallback (::fltk::Widget *widget, void *data) +void FltkListResource::setWidgetStyle (Fl_Widget *widget, + core::style::Style *style) { - ::fltk::Widget *fltkItem = ((::fltk::Menu *) widget)->item (); + Fl_Tree *t = (Fl_Tree *)widget; + + FltkResource::setWidgetStyle(widget, style); + + t->item_labelfont(widget->labelfont()); + t->item_labelsize(widget->labelsize()); + t->item_labelfgcolor(widget->labelcolor()); + t->item_labelbgcolor(widget->color()); +} + +void FltkListResource::widgetCallback (Fl_Widget *widget, void *data) +{ + Fl_Tree_Item *fltkItem = ((Fl_Tree *) widget)->callback_item (); int index = -1; if (fltkItem) index = (long) (fltkItem->user_data ()); if (index > -1) { - /* A MultiBrowser will trigger a callback for each item that is - * selected and each item that is deselected, but a "plain" - * Browser will only trigger the callback for the newly selected item - * (for which selected() is false, incidentally). - */ FltkListResource *res = (FltkListResource *) data; - if (res->mode == SELECTION_MULTIPLE) { - bool selected = fltkItem->selected (); - res->itemsSelected.set (index, selected); + bool selected = fltkItem->is_selected (); + res->itemsSelected.set (index, selected); + } +} + +void *FltkListResource::newItem (const char *str, bool enabled, bool selected) +{ + Fl_Tree *tree = (Fl_Tree *) widget; + Fl_Tree_Item *parent = (Fl_Tree_Item *)currParent; + Fl_Tree_Item *item = tree->add(parent, str); + int index = itemsSelected.size(); + + enabled &= parent->is_active(); + item->activate(enabled); + item->user_data((void*)(long)index); + itemsSelected.increase (); + itemsSelected.set (itemsSelected.size() - 1, selected); + + return item; +} + +void FltkListResource::addItem (const char *str, bool enabled, bool selected) +{ + Fl_Tree *tree = (Fl_Tree *) widget; + Fl_Tree_Item *item = (Fl_Tree_Item *) newItem(str, enabled, selected); + + if (selected) { + if (mode == SELECTION_MULTIPLE) { + item->select(selected); } else { - int size = res->itemsSelected.size(); - for (int i = 0; i < size; i++) - res->itemsSelected.set (i, false); - res->itemsSelected.set (index, true); + const bool do_callback = true; + tree->select_only(item, do_callback); } } + queueResize (true); } -void FltkListResource::addItem (const char *str, bool enabled, bool selected) +void FltkListResource::pushGroup (const char *name, bool enabled) { - FltkSelectionResource<dw::core::ui::ListResource>::addItem - (str,enabled,selected); - int index = itemsSelected.size (); - itemsSelected.increase (); - itemsSelected.set (index,selected); + bool selected = false; + + /* TODO: make it impossible to select a group */ + currParent = (Fl_Tree_Item *) newItem(name, enabled, selected); queueResize (true); } +void FltkListResource::popGroup () +{ + Fl_Tree_Item *p = (Fl_Tree_Item *)currParent; + + if (p->parent()) + currParent = p->parent(); +} + +int FltkListResource::getMaxItemWidth() +{ + Fl_Tree *tree = (Fl_Tree *)widget; + int max = 0; + + for (Fl_Tree_Item *i = tree->first(); i; i = tree->next(i)) { + int width = 0; + + if (i == tree->root()) + continue; + + for (Fl_Tree_Item *p = i->parent(); p != tree->root(); p = p->parent()) + width += tree->connectorwidth(); + + if (i->label()) + width += fl_width(i->label()); + + if (width > max) + max = width; + } + return max; +} + void FltkListResource::sizeRequest (core::Requisition *requisition) { if (style) { FltkFont *font = (FltkFont*)style->font; - ::fltk::setfont(font->font,font->size); + fl_font(font->font,font->size); int rows = getNumberOfItems(); if (showRows < rows) { rows = showRows; } - /* - * The widget sometimes shows scrollbars when they are not required. - * The following values try to keep any scrollbars from obscuring - * options, at the cost of showing too much whitespace at times. - */ - requisition->width = getMaxStringWidth() + 24; - requisition->ascent = font->ascent + 2 + + requisition->width = getMaxItemWidth() + 5 + Fl::scrollbar_size();; + requisition->ascent = font->ascent + 5 + (rows - 1) * (font->ascent + font->descent + 1); requisition->descent = font->descent + 3; } else { diff --git a/dw/fltkui.hh b/dw/fltkui.hh index 245d5aad..ff927c80 100644 --- a/dw/fltkui.hh +++ b/dw/fltkui.hh @@ -5,11 +5,9 @@ # error Do not include this file directly, use "fltkcore.hh" instead. #endif -#include <fltk/Button.h> -#include <fltk/Menu.h> -#include <fltk/TextBuffer.h> -#include <fltk/Item.h> -#include <fltk/ItemGroup.h> +#include <FL/Fl_Button.H> +#include <FL/Fl_Menu.H> +#include <FL/Fl_Text_Buffer.H> namespace dw { namespace fltk { @@ -179,7 +177,7 @@ private: protected: FltkView *view; - ::fltk::Widget *widget; + Fl_Widget *widget; core::Allocation allocation; FltkPlatform *platform; @@ -187,9 +185,9 @@ protected: FltkResource (FltkPlatform *platform); void init (FltkPlatform *platform); - virtual ::fltk::Widget *createNewWidget (core::Allocation *allocation) = 0; + virtual Fl_Widget *createNewWidget (core::Allocation *allocation) = 0; - void setWidgetStyle (::fltk::Widget *widget, core::style::Style *style); + virtual void setWidgetStyle (Fl_Widget *widget, core::style::Style *style); void setDisplayed (bool displayed); bool displayed(); public: @@ -229,10 +227,10 @@ class FltkLabelButtonResource: private: const char *label; - static void widgetCallback (::fltk::Widget *widget, void *data); + static void widgetCallback (Fl_Widget *widget, void *data); protected: - ::fltk::Widget *createNewWidget (core::Allocation *allocation); + Fl_Widget *createNewWidget (core::Allocation *allocation); public: FltkLabelButtonResource (FltkPlatform *platform, const char *label); @@ -251,7 +249,7 @@ class FltkComplexButtonResource: private: bool relief; - static void widgetCallback (::fltk::Widget *widget, void *data); + static void widgetCallback (Fl_Widget *widget, void *data); protected: FltkView *topView, *flatView; @@ -267,7 +265,7 @@ protected: int reliefXThickness (); int reliefYThickness (); - ::fltk::Widget *createNewWidget (core::Allocation *allocation); + Fl_Widget *createNewWidget (core::Allocation *allocation); public: FltkComplexButtonResource (FltkPlatform *platform, dw::core::Widget *widget, @@ -288,13 +286,15 @@ private: bool password; const char *initText; char *label; + int label_w; bool editable; - static void widgetCallback (::fltk::Widget *widget, void *data); + static void widgetCallback (Fl_Widget *widget, void *data); void setDisplayed (bool displayed); protected: - ::fltk::Widget *createNewWidget (core::Allocation *allocation); + Fl_Widget *createNewWidget (core::Allocation *allocation); + void setWidgetStyle (Fl_Widget *widget, core::style::Style *style); public: FltkEntryResource (FltkPlatform *platform, int maxLength, bool password, @@ -302,6 +302,7 @@ public: ~FltkEntryResource (); void sizeRequest (core::Requisition *requisition); + void sizeAllocate (core::Allocation *allocation); const char *getText (); void setText (const char *text); @@ -314,12 +315,14 @@ class FltkMultiLineTextResource: public FltkSpecificResource <dw::core::ui::MultiLineTextResource> { private: - ::fltk::TextBuffer *buffer; + Fl_Text_Buffer *buffer; + char *text_copy; bool editable; int numCols, numRows; protected: - ::fltk::Widget *createNewWidget (core::Allocation *allocation); + Fl_Widget *createNewWidget (core::Allocation *allocation); + void setWidgetStyle (Fl_Widget *widget, core::style::Style *style); public: FltkMultiLineTextResource (FltkPlatform *platform, int cols, int rows); @@ -341,8 +344,9 @@ private: bool initActivated; protected: - virtual ::fltk::Button *createNewButton (core::Allocation *allocation) = 0; - ::fltk::Widget *createNewWidget (core::Allocation *allocation); + virtual Fl_Button *createNewButton (core::Allocation *allocation) = 0; + Fl_Widget *createNewWidget (core::Allocation *allocation); + void setWidgetStyle (Fl_Widget *widget, core::style::Style *style); public: FltkToggleButtonResource (FltkPlatform *platform, @@ -360,7 +364,7 @@ class FltkCheckButtonResource: public FltkToggleButtonResource <dw::core::ui::CheckButtonResource> { protected: - ::fltk::Button *createNewButton (core::Allocation *allocation); + Fl_Button *createNewButton (core::Allocation *allocation); public: FltkCheckButtonResource (FltkPlatform *platform, @@ -401,7 +405,8 @@ private: public: Group (FltkRadioButtonResource *radioButtonResource); - inline lout::container::typed::Iterator <FltkRadioButtonResource> iterator () + inline lout::container::typed::Iterator <FltkRadioButtonResource> + iterator () { return list->iterator (); } @@ -418,11 +423,11 @@ private: Group *group; - static void widgetCallback (::fltk::Widget *widget, void *data); + static void widgetCallback (Fl_Widget *widget, void *data); void buttonClicked (); protected: - ::fltk::Button *createNewButton (core::Allocation *allocation); + Fl_Button *createNewButton (core::Allocation *allocation); public: FltkRadioButtonResource (FltkPlatform *platform, @@ -438,60 +443,14 @@ template <class I> class FltkSelectionResource: public FltkSpecificResource <I> { protected: - class Item: public lout::object::Object - { - public: - enum Type { ITEM, START, END } type; - - const char *name; - bool enabled, initSelected; - - Item (Type type, const char *name = NULL, bool enabled = true, - bool selected = false); - ~Item (); - - ::fltk::Item *createNewWidget (int index); - ::fltk::ItemGroup *createNewGroupWidget (); - }; - - class WidgetStack: public lout::object::Object - { - public: - ::fltk::Menu *widget; - lout::container::typed::Stack <lout::object::TypedPointer < ::fltk::Menu> > *stack; - - WidgetStack (::fltk::Menu *widget); - ~WidgetStack (); - }; - - lout::container::typed::List <WidgetStack> *widgetStacks; - lout::container::typed::List <Item> *allItems; - lout::container::typed::Vector <Item> *items; - - Item *createNewItem (typename Item::Type type, - const char *name = NULL, - bool enabled = true, - bool selected = false); - - ::fltk::Widget *createNewWidget (core::Allocation *allocation); - virtual ::fltk::Menu *createNewMenu (core::Allocation *allocation) = 0; virtual bool setSelectedItems() { return false; } - - int getMaxStringWidth (); - + virtual void addItem (const char *str, bool enabled, bool selected) = 0; + virtual void pushGroup (const char *name, bool enabled) = 0; + virtual void popGroup () = 0; public: - FltkSelectionResource (FltkPlatform *platform); - ~FltkSelectionResource (); - + FltkSelectionResource (FltkPlatform *platform) : + FltkSpecificResource<I> (platform) {}; dw::core::Iterator *iterator (dw::core::Content::Type mask, bool atEnd); - - void addItem (const char *str, bool enabled, bool selected); - - void pushGroup (const char *name, bool enabled); - void popGroup (); - - int getNumberOfItems (); - const char *getItem (int index); }; @@ -499,18 +458,25 @@ class FltkOptionMenuResource: public FltkSelectionResource <dw::core::ui::OptionMenuResource> { protected: - ::fltk::Menu *createNewMenu (core::Allocation *allocation); + Fl_Widget *createNewWidget (core::Allocation *allocation); virtual bool setSelectedItems() { return true; } - + void setWidgetStyle (Fl_Widget *widget, core::style::Style *style); + int getNumberOfItems(); + int getMaxItemWidth (); private: - static void widgetCallback (::fltk::Widget *widget, void *data); - int selection; - + static void widgetCallback (Fl_Widget *widget, void *data); + void enlargeMenu(); + Fl_Menu_Item *newItem(); + Fl_Menu_Item *menu; + int itemsAllocated, itemsUsed; + int visibleItems; /* not counting the invisible ones that close a group */ public: FltkOptionMenuResource (FltkPlatform *platform); ~FltkOptionMenuResource (); void addItem (const char *str, bool enabled, bool selected); + void pushGroup (const char *name, bool enabled); + void popGroup (); void sizeRequest (core::Requisition *requisition); bool isSelected (int index); @@ -520,10 +486,16 @@ class FltkListResource: public FltkSelectionResource <dw::core::ui::ListResource> { protected: - ::fltk::Menu *createNewMenu (core::Allocation *allocation); + Fl_Widget *createNewWidget (core::Allocation *allocation); + void setWidgetStyle (Fl_Widget *widget, core::style::Style *style); + + int getNumberOfItems () {return itemsSelected.size();}; + int getMaxItemWidth (); private: - static void widgetCallback (::fltk::Widget *widget, void *data); + static void widgetCallback (Fl_Widget *widget, void *data); + void *newItem (const char *str, bool enabled, bool selected); + void *currParent; lout::misc::SimpleVector <bool> itemsSelected; int showRows; ListResource::SelectionMode mode; @@ -534,6 +506,8 @@ public: ~FltkListResource (); void addItem (const char *str, bool enabled, bool selected); + void pushGroup (const char *name, bool enabled); + void popGroup (); void sizeRequest (core::Requisition *requisition); bool isSelected (int index); diff --git a/dw/fltkviewbase.cc b/dw/fltkviewbase.cc index cab22cf4..bf3aba22 100644 --- a/dw/fltkviewbase.cc +++ b/dw/fltkviewbase.cc @@ -21,40 +21,63 @@ #include "fltkviewport.hh" -#include <fltk/draw.h> -#include <fltk/damage.h> -#include <fltk/layout.h> -#include <fltk/events.h> -#include <fltk/Cursor.h> -#include <fltk/run.h> -#include <fltk/utf.h> +#include <FL/Fl.H> +#include <FL/fl_draw.H> #include <stdio.h> -#include <wchar.h> -#include <wctype.h> #include "../lout/msg.h" -using namespace fltk; +extern Fl_Widget* fl_oldfocus; + using namespace lout::object; using namespace lout::container::typed; namespace dw { namespace fltk { -::fltk::Image *FltkViewBase::backBuffer; +FltkViewBase::BackBuffer::BackBuffer () +{ + w = 0; + h = 0; + created = false; +} + +FltkViewBase::BackBuffer::~BackBuffer () +{ + if (created) + fl_delete_offscreen (offscreen); +} + +void FltkViewBase::BackBuffer::setSize (int w, int h) +{ + if (!created || w > this->w || h > this->h) { + this->w = w; + this->h = h; + if (created) + fl_delete_offscreen (offscreen); + offscreen = fl_create_offscreen (w, h); + created = true; + } +} + +FltkViewBase::BackBuffer *FltkViewBase::backBuffer; bool FltkViewBase::backBufferInUse; FltkViewBase::FltkViewBase (int x, int y, int w, int h, const char *label): - Group (x, y, w, h, label) + Fl_Group (x, y, w, h, label) { + Fl_Group::current(0); canvasWidth = 1; canvasHeight = 1; - bgColor = WHITE; + bgColor = FL_WHITE; mouse_x = mouse_y = 0; + focused_child = NULL; exposeArea = NULL; if (backBuffer == NULL) { - backBuffer = new Image (); + backBuffer = new BackBuffer (); } + box(FL_NO_BOX); + resizable(NULL); } FltkViewBase::~FltkViewBase () @@ -64,7 +87,7 @@ FltkViewBase::~FltkViewBase () void FltkViewBase::setBufferedDrawing (bool b) { if (b && backBuffer == NULL) { - backBuffer = new Image (); + backBuffer = new BackBuffer (); } else if (!b && backBuffer != NULL) { delete backBuffer; backBuffer = NULL; @@ -75,7 +98,7 @@ void FltkViewBase::draw () { int d = damage (); - if ((d & DAMAGE_VALUE) && !(d & DAMAGE_EXPOSE)) { + if ((d & FL_DAMAGE_USER1) && !(d & FL_DAMAGE_EXPOSE)) { lout::container::typed::Iterator <core::Rectangle> it; for (it = drawRegion.rectangles (); it.hasNext (); ) { @@ -83,22 +106,22 @@ void FltkViewBase::draw () } drawRegion.clear (); - d &= ~DAMAGE_VALUE; + d &= ~FL_DAMAGE_USER1; } - if (d & DAMAGE_CHILD) { + if (d & FL_DAMAGE_CHILD) { drawChildWidgets (); - d &= ~DAMAGE_CHILD; + d &= ~FL_DAMAGE_CHILD; } if (d) { dw::core::Rectangle rect ( - translateViewXToCanvasX (0), - translateViewYToCanvasY (0), + translateViewXToCanvasX (x ()), + translateViewYToCanvasY (y ()), w (), h ()); - if (d == DAMAGE_SCROLL) { + if (d == FL_DAMAGE_SCROLL) { // a clipping rectangle has already been set by fltk::scrollrect () draw (&rect, DRAW_PLAIN); } else { @@ -111,88 +134,84 @@ void FltkViewBase::draw () void FltkViewBase::draw (const core::Rectangle *rect, DrawType type) { - int offsetX = 0, offsetY = 0; - - /* fltk-clipping does not use widget coordinates */ - transform (offsetX, offsetY); - - ::fltk::Rectangle viewRect ( - translateCanvasXToViewX (rect->x) + offsetX, - translateCanvasYToViewY (rect->y) + offsetY, - rect->width, rect->height); - - ::fltk::intersect_with_clip (viewRect); - - viewRect.x (viewRect.x () - offsetX); - viewRect.y (viewRect.y () - offsetY); - - if (! viewRect.empty ()) { - dw::core::Rectangle r ( - translateViewXToCanvasX (viewRect.x ()), - translateViewYToCanvasY (viewRect.y ()), - viewRect.w (), - viewRect.h ()); - - exposeArea = &viewRect; - - if (type == DRAW_BUFFERED && backBuffer && !backBufferInUse) { - backBufferInUse = true; - { - GSave gsave; - - backBuffer->setsize (viewRect.w (), viewRect.h ()); - backBuffer->make_current (); - translate (-viewRect.x (), -viewRect.y ()); - - setcolor (bgColor); - fillrect (viewRect); - theLayout->expose (this, &r); - } - - backBuffer->draw (Rectangle (0, 0, viewRect.w (), viewRect.h ()), - viewRect); - - backBufferInUse = false; - } else if (type == DRAW_BUFFERED || type == DRAW_CLIPPED) { - // if type == DRAW_BUFFERED but we do not have backBuffer available - // we fall back to clipped drawing - push_clip (viewRect); - setcolor (bgColor); - fillrect (viewRect); - theLayout->expose (this, &r); - pop_clip (); - } else { - setcolor (bgColor); - fillrect (viewRect); - theLayout->expose (this, &r); - } - - exposeArea = NULL; + int X = translateCanvasXToViewX (rect->x); + int Y = translateCanvasYToViewY (rect->y); + int W, H; + + // fl_clip_box() can't handle values greater than SHRT_MAX! + if (X > x () + w () || Y > y () + h ()) + return; + + W = X + rect->width > x () + w () ? x () + w () - X : rect->width; + H = Y + rect->height > y () + h () ? y () + h () - Y : rect->height; + + fl_clip_box(X, Y, W, H, X, Y, W, H); + + core::Rectangle r (translateViewXToCanvasX (X), + translateViewYToCanvasY (Y), W, H); + + if (r.isEmpty ()) + return; + + exposeArea = &r; + + if (type == DRAW_BUFFERED && backBuffer && !backBufferInUse) { + backBufferInUse = true; + backBuffer->setSize (X + W, Y + H); // would be nicer to use (W, H)... + fl_begin_offscreen (backBuffer->offscreen); + fl_push_matrix (); + fl_color (bgColor); + fl_rectf (X, Y, W, H); + theLayout->expose (this, &r); + fl_pop_matrix (); + fl_end_offscreen (); + fl_copy_offscreen (X, Y, W, H, backBuffer->offscreen, X, Y); + backBufferInUse = false; + } else if (type == DRAW_BUFFERED || type == DRAW_CLIPPED) { + // if type == DRAW_BUFFERED but we do not have backBuffer available + // we fall back to clipped drawing + fl_push_clip (X, Y, W, H); + fl_color (bgColor); + fl_rectf (X, Y, W, H); + theLayout->expose (this, &r); + fl_pop_clip (); + } else { + fl_color (bgColor); + fl_rectf (X, Y, W, H); + theLayout->expose (this, &r); } + // DEBUG: + //fl_color(FL_RED); + //fl_rect(X, Y, W, H); + + exposeArea = NULL; } void FltkViewBase::drawChildWidgets () { for (int i = children () - 1; i >= 0; i--) { - Widget& w = *child(i); + Fl_Widget& w = *child(i); +#if 0 +PORT1.3 if (w.damage() & DAMAGE_CHILD_LABEL) { draw_outside_label(w); w.set_damage(w.damage() & ~DAMAGE_CHILD_LABEL); } +#endif update_child(w); } } core::ButtonState getDwButtonState () { - int s1 = event_state (); + int s1 = Fl::event_state (); int s2 = (core::ButtonState)0; - if (s1 & SHIFT) s2 |= core::SHIFT_MASK; - if (s1 & CTRL) s2 |= core::CONTROL_MASK; - if (s1 & ALT) s2 |= core::META_MASK; - if (s1 & BUTTON1) s2 |= core::BUTTON1_MASK; - if (s1 & BUTTON2) s2 |= core::BUTTON2_MASK; - if (s1 & BUTTON3) s2 |= core::BUTTON3_MASK; + if (s1 & FL_SHIFT) s2 |= core::SHIFT_MASK; + if (s1 & FL_CTRL) s2 |= core::CONTROL_MASK; + if (s1 & FL_ALT) s2 |= core::META_MASK; + if (s1 & FL_BUTTON1) s2 |= core::BUTTON1_MASK; + if (s1 & FL_BUTTON2) s2 |= core::BUTTON2_MASK; + if (s1 & FL_BUTTON3) s2 |= core::BUTTON3_MASK; return (core::ButtonState)s2; } @@ -207,61 +226,79 @@ int FltkViewBase::handle (int event) * when passed a fltk::PUSH event. " */ switch(event) { - case PUSH: + case FL_PUSH: + /* Hide the tooltip */ + theLayout->cancelTooltip(); + processed = - theLayout->buttonPress (this, event_clicks () + 1, - translateViewXToCanvasX (event_x ()), - translateViewYToCanvasY (event_y ()), - getDwButtonState (), event_button ()); + theLayout->buttonPress (this, Fl::event_clicks () + 1, + translateViewXToCanvasX (Fl::event_x ()), + translateViewYToCanvasY (Fl::event_y ()), + getDwButtonState (), Fl::event_button ()); _MSG("PUSH => %s\n", processed ? "true" : "false"); if (processed) { /* pressed dw content; give focus to the view */ - ::fltk::focus(this); + Fl::focus(this); + return true; } - return processed ? true : Group::handle (event); - - case RELEASE: + break; + case FL_RELEASE: processed = - theLayout->buttonRelease (this, event_clicks () + 1, - translateViewXToCanvasX (event_x ()), - translateViewYToCanvasY (event_y ()), - getDwButtonState (), event_button ()); + theLayout->buttonRelease (this, Fl::event_clicks () + 1, + translateViewXToCanvasX (Fl::event_x ()), + translateViewYToCanvasY (Fl::event_y ()), + getDwButtonState (), Fl::event_button ()); _MSG("RELEASE => %s\n", processed ? "true" : "false"); - return processed ? true : Group::handle (event); - - case MOVE: - mouse_x = event_x(); - mouse_y = event_y(); + if (processed) + return true; + break; + case FL_MOVE: + mouse_x = Fl::event_x(); + mouse_y = Fl::event_y(); processed = theLayout->motionNotify (this, translateViewXToCanvasX (mouse_x), translateViewYToCanvasY (mouse_y), getDwButtonState ()); _MSG("MOVE => %s\n", processed ? "true" : "false"); - return processed ? true : Group::handle (event); - - case DRAG: + if (processed) + return true; + break; + case FL_DRAG: processed = theLayout->motionNotify (this, - translateViewXToCanvasX (event_x ()), - translateViewYToCanvasY (event_y ()), + translateViewXToCanvasX (Fl::event_x ()), + translateViewYToCanvasY (Fl::event_y ()), getDwButtonState ()); _MSG("DRAG => %s\n", processed ? "true" : "false"); - return processed ? true : Group::handle (event); - - case ENTER: - theLayout->enterNotify (this, translateViewXToCanvasX (event_x ()), - translateViewYToCanvasY (event_y ()), + if (processed) + return true; + break; + case FL_ENTER: + theLayout->enterNotify (this, + translateViewXToCanvasX (Fl::event_x ()), + translateViewYToCanvasY (Fl::event_y ()), getDwButtonState ()); - return Group::handle (event); - - case LEAVE: + break; + case FL_HIDE: + /* WORKAROUND: strangely, the tooltip window is not automatically hidden + * with its parent. Here we fake a LEAVE to achieve it. */ + case FL_LEAVE: theLayout->leaveNotify (this, getDwButtonState ()); - return Group::handle (event); - + break; + case FL_FOCUS: + if (focused_child && find(focused_child) < children()) { + /* strangely, find() == children() if the child is not found */ + focused_child->take_focus(); + } + return 1; + case FL_UNFOCUS: + focused_child = fl_oldfocus; + return 0; default: - return Group::handle (event); + break; } + return Fl_Group::handle (event); } // ---------------------------------------------------------------------- @@ -269,6 +306,8 @@ int FltkViewBase::handle (int event) void FltkViewBase::setLayout (core::Layout *layout) { theLayout = layout; + if (usesViewport()) + theLayout->viewportSizeChanged(this, w(), h()); } void FltkViewBase::setCanvasSize (int width, int ascent, int descent) @@ -279,55 +318,32 @@ void FltkViewBase::setCanvasSize (int width, int ascent, int descent) void FltkViewBase::setCursor (core::style::Cursor cursor) { - static Cursor *mapDwToFltk[] = { - CURSOR_CROSS, - CURSOR_DEFAULT, - CURSOR_HAND, - CURSOR_MOVE, - CURSOR_WE, - CURSOR_NESW, - CURSOR_NWSE, - CURSOR_NS, - CURSOR_NWSE, - CURSOR_NESW, - CURSOR_NS, - CURSOR_WE, - CURSOR_INSERT, - CURSOR_WAIT, - CURSOR_HELP - }; - - /* - static char *cursorName[] = { - "CURSOR_CROSS", - "CURSOR_DEFAULT", - "CURSOR_HAND", - "CURSOR_MOVE", - "CURSOR_WE", - "CURSOR_NESW", - "CURSOR_NWSE", - "CURSOR_NS", - "CURSOR_NWSE", - "CURSOR_NESW", - "CURSOR_NS", - "CURSOR_WE", - "CURSOR_INSERT", - "CURSOR_WAIT", - "CURSOR_HELP" + static Fl_Cursor mapDwToFltk[] = { + FL_CURSOR_CROSS, + FL_CURSOR_DEFAULT, + FL_CURSOR_HAND, + FL_CURSOR_MOVE, + FL_CURSOR_WE, + FL_CURSOR_NESW, + FL_CURSOR_NWSE, + FL_CURSOR_NS, + FL_CURSOR_NWSE, + FL_CURSOR_NESW, + FL_CURSOR_NS, + FL_CURSOR_WE, + FL_CURSOR_INSERT, + FL_CURSOR_WAIT, + FL_CURSOR_HELP }; - MSG("Cursor changes to '%s'.\n", cursorName[cursor]); - */ - - /** \bug Does not work */ - this->cursor (mapDwToFltk[cursor]); + fl_cursor (mapDwToFltk[cursor]); } void FltkViewBase::setBgColor (core::style::Color *color) { bgColor = color ? ((FltkColor*)color)->colors[dw::core::style::Color::SHADING_NORMAL] : - WHITE; + FL_WHITE; } void FltkViewBase::startDrawing (core::Rectangle *area) @@ -342,12 +358,12 @@ void FltkViewBase::queueDraw (core::Rectangle *area) { drawRegion.addRectangle (area); /** DAMAGE_VALUE is just an arbitrary value other than DAMAGE_EXPOSE here */ - redraw (DAMAGE_VALUE); + damage (FL_DAMAGE_USER1); } void FltkViewBase::queueDrawTotal () { - redraw (DAMAGE_EXPOSE); + damage (FL_DAMAGE_EXPOSE); } void FltkViewBase::cancelQueueDraw () @@ -364,9 +380,16 @@ void FltkViewBase::drawLine (core::style::Color *color, core::style::Color::Shading shading, int x1, int y1, int x2, int y2) { - setcolor(((FltkColor*)color)->colors[shading]); - drawline (translateCanvasXToViewX (x1), translateCanvasYToViewY (y1), - translateCanvasXToViewX (x2), translateCanvasYToViewY (y2)); + fl_color(((FltkColor*)color)->colors[shading]); + // we clip with a large border (5000px), as clipping causes artefacts + // with non-solid line styles. + // However it's still better than no clipping at all. + clipPoint (&x1, &y1, 5000); + clipPoint (&x2, &y2, 5000); + fl_line (translateCanvasXToViewX (x1), + translateCanvasYToViewY (y1), + translateCanvasXToViewX (x2), + translateCanvasYToViewY (y2)); } void FltkViewBase::drawTypedLine (core::style::Color *color, @@ -385,42 +408,42 @@ void FltkViewBase::drawTypedLine (core::style::Color *color, d = len % f*width; gap = ng ? d/ng + (w > 3 ? 2 : 0) : 0; dashes[0] = 1; dashes[1] = f*width-gap; dashes[2] = 0; - line_style(::fltk::DASH + ::fltk::CAP_ROUND, w, dashes); + fl_line_style(FL_DASH + FL_CAP_ROUND, w, dashes); /* These formulas also work, but ain't pretty ;) - * line_style(::fltk::DOT + ::fltk::CAP_ROUND, w); + * fl_line_style(FL_DOT + FL_CAP_ROUND, w); * dashes[0] = 1; dashes[1] = 3*width-2; dashes[2] = 0; */ } else if (type == core::style::LINE_DASHED) { - line_style(::fltk::DASH + ::fltk::CAP_ROUND, w); + fl_line_style(FL_DASH + FL_CAP_ROUND, w); } - setcolor(((FltkColor*)color)->colors[shading]); + fl_color(((FltkColor*)color)->colors[shading]); drawLine (color, shading, x1, y1, x2, y2); if (type != core::style::LINE_NORMAL) - line_style(::fltk::SOLID); + fl_line_style(FL_SOLID); } void FltkViewBase::drawRectangle (core::style::Color *color, core::style::Color::Shading shading, bool filled, - int x, int y, int width, int height) + int X, int Y, int width, int height) { - setcolor(((FltkColor*)color)->colors[shading]); + fl_color(((FltkColor*)color)->colors[shading]); if (width < 0) { - x += width; + X += width; width = -width; } if (height < 0) { - y += height; + Y += height; height = -height; } - int x1 = translateCanvasXToViewX (x); - int y1 = translateCanvasYToViewY (y); - int x2 = translateCanvasXToViewX (x + width); - int y2 = translateCanvasYToViewY (y + height); + int x1 = X; + int y1 = Y; + int x2 = X + width; + int y2 = Y + height; // We only support rectangles with line width 1px, so we clip with // a rectangle 1px wider and higher than what we actually expose. @@ -428,11 +451,15 @@ void FltkViewBase::drawRectangle (core::style::Color *color, clipPoint (&x1, &y1, 1); clipPoint (&x2, &y2, 1); - ::fltk::Rectangle rect (x1, y1, x2 - x1, y2 - y1); + x1 = translateCanvasXToViewX (x1); + y1 = translateCanvasYToViewY (y1); + x2 = translateCanvasXToViewX (x2); + y2 = translateCanvasYToViewY (y2); + if (filled) - fillrect (rect); + fl_rectf (x1, y1, x2 - x1, y2 - y1); else - strokerect (rect); + fl_rect (x1, y1, x2 - x1, y2 - y1); } void FltkViewBase::drawArc (core::style::Color *color, @@ -440,47 +467,55 @@ void FltkViewBase::drawArc (core::style::Color *color, int centerX, int centerY, int width, int height, int angle1, int angle2) { - setcolor(((FltkColor*)color)->colors[shading]); + fl_color(((FltkColor*)color)->colors[shading]); int x = translateCanvasXToViewX (centerX) - width / 2; int y = translateCanvasYToViewY (centerY) - height / 2; - ::fltk::Rectangle rect (x, y, width, height); - addchord(rect, angle1, angle2); - closepath(); + + fl_arc(x, y, width, height, angle1, angle2); if (filled) - fillpath(); - else - strokepath(); + fl_pie(x, y, width, height, angle1, angle2); } void FltkViewBase::drawPolygon (core::style::Color *color, core::style::Color::Shading shading, - bool filled, int points[][2], int npoints) + bool filled, bool convex, core::Point *points, + int npoints) { if (npoints > 0) { + fl_color(((FltkColor*)color)->colors[shading]); + + if (filled) { + if (convex) + fl_begin_polygon(); + else + fl_begin_complex_polygon(); + } else + fl_begin_loop(); + for (int i = 0; i < npoints; i++) { - points[i][0] = translateCanvasXToViewX(points[i][0]); - points[i][1] = translateCanvasYToViewY(points[i][1]); + fl_vertex(translateCanvasXToViewX(points[i].x), + translateCanvasYToViewY(points[i].y)); } - setcolor(((FltkColor*)color)->colors[shading]); - addvertices(npoints, points); - closepath(); - if (filled) - fillpath(); - else - strokepath(); + if (filled) { + if (convex) + fl_end_polygon(); + else + fl_end_complex_polygon(); + } else + fl_end_loop(); } } core::View *FltkViewBase::getClippingView (int x, int y, int width, int height) { - push_clip (translateCanvasXToViewX (x), translateCanvasYToViewY (y), - width, height); + fl_push_clip (translateCanvasXToViewX (x), translateCanvasYToViewY (y), + width, height); return this; } void FltkViewBase::mergeClippingView (core::View *clippingView) { - pop_clip (); + fl_pop_clip (); } // ---------------------------------------------------------------------- @@ -495,80 +530,83 @@ FltkWidgetView::~FltkWidgetView () { } -void FltkWidgetView::layout () { - /** - * pass layout to child widgets. This is needed for complex fltk - * widgets as TextEditor. - * We can't use Group::layout() as that would rearrange the widgets. - */ - for (int i = children () - 1; i >= 0; i--) { - ::fltk::Widget *widget = child (i); - - if (widget->layout_damage ()) { - widget->layout (); - } - } -} - void FltkWidgetView::drawText (core::style::Font *font, core::style::Color *color, core::style::Color::Shading shading, - int x, int y, const char *text, int len) + int X, int Y, const char *text, int len) { FltkFont *ff = (FltkFont*)font; - setfont(ff->font, ff->size); - setcolor(((FltkColor*)color)->colors[shading]); + fl_font(ff->font, ff->size); + fl_color(((FltkColor*)color)->colors[shading]); if (!font->letterSpacing && !font->fontVariant) { - drawtext(text, len, - translateCanvasXToViewX (x), translateCanvasYToViewY (y)); + fl_draw(text, len, + translateCanvasXToViewX (X), translateCanvasYToViewY (Y)); } else { /* Nonzero letter spacing adjustment, draw each glyph individually */ - int viewX = translateCanvasXToViewX (x), - viewY = translateCanvasYToViewY (y); + int viewX = translateCanvasXToViewX (X), + viewY = translateCanvasYToViewY (Y); int curr = 0, next = 0, nb; char chbuf[4]; - wchar_t wc, wcu; + int c, cu; - if (font->fontVariant == 1) { + if (font->fontVariant == core::style::FONT_VARIANT_SMALL_CAPS) { int sc_fontsize = lout::misc::roundInt(ff->size * 0.78); for (curr = 0; next < len; curr = next) { next = theLayout->nextGlyph(text, curr); - wc = utf8decode(text + curr, text + next, &nb); - if ((wcu = towupper(wc)) == wc) { + c = fl_utf8decode(text + curr, text + next, &nb); + if ((cu = fl_toupper(c)) == c) { /* already uppercase, just draw the character */ - setfont(ff->font, ff->size); - drawtext(text + curr, next - curr, viewX, viewY); + fl_font(ff->font, ff->size); + fl_draw(text + curr, next - curr, viewX, viewY); viewX += font->letterSpacing; - viewX += (int)getwidth(text + curr, next - curr); + viewX += (int)fl_width(text + curr, next - curr); } else { /* make utf8 string for converted char */ - nb = utf8encode(wcu, chbuf); - setfont(ff->font, sc_fontsize); - drawtext(chbuf, nb, viewX, viewY); + nb = fl_utf8encode(cu, chbuf); + fl_font(ff->font, sc_fontsize); + fl_draw(chbuf, nb, viewX, viewY); viewX += font->letterSpacing; - viewX += (int)getwidth(chbuf, nb); + viewX += (int)fl_width(chbuf, nb); } } } else { while (next < len) { next = theLayout->nextGlyph(text, curr); - drawtext(text + curr, next - curr, viewX, viewY); + fl_draw(text + curr, next - curr, viewX, viewY); viewX += font->letterSpacing + - (int)getwidth(text + curr,next - curr); + (int)fl_width(text + curr,next - curr); curr = next; } } } } +/* + * "simple" in that it ignores letter-spacing, etc. This was added for image + * alt text where none of that matters. + */ +void FltkWidgetView::drawSimpleWrappedText (core::style::Font *font, + core::style::Color *color, + core::style::Color::Shading shading, + int X, int Y, int W, int H, + const char *text) +{ + FltkFont *ff = (FltkFont*)font; + fl_font(ff->font, ff->size); + fl_color(((FltkColor*)color)->colors[shading]); + fl_draw(text, + translateCanvasXToViewX (X), translateCanvasYToViewY (Y), + W, H, FL_ALIGN_TOP|FL_ALIGN_LEFT|FL_ALIGN_WRAP, NULL, 0); +} + void FltkWidgetView::drawImage (core::Imgbuf *imgbuf, int xRoot, int yRoot, - int x, int y, int width, int height) + int X, int Y, int width, int height) { ((FltkImgbuf*)imgbuf)->draw (this, translateCanvasXToViewX (xRoot), translateCanvasYToViewY (yRoot), - x, y, width, height); + X, Y, width, height); } bool FltkWidgetView::usesFltkWidgets () @@ -576,36 +614,32 @@ bool FltkWidgetView::usesFltkWidgets () return true; } -void FltkWidgetView::addFltkWidget (::fltk::Widget *widget, - core::Allocation *allocation) +void FltkWidgetView::addFltkWidget (Fl_Widget *widget, + core::Allocation *allocation) { allocateFltkWidget (widget, allocation); add (widget); } -void FltkWidgetView::removeFltkWidget (::fltk::Widget *widget) +void FltkWidgetView::removeFltkWidget (Fl_Widget *widget) { remove (widget); } -void FltkWidgetView::allocateFltkWidget (::fltk::Widget *widget, +void FltkWidgetView::allocateFltkWidget (Fl_Widget *widget, core::Allocation *allocation) { - widget->x (translateCanvasXToViewX (allocation->x)); - widget->y (translateCanvasYToViewY (allocation->y)); - widget->w (allocation->width); - widget->h (allocation->ascent + allocation->descent); - - /* widgets created tiny and later resized need this flag to display */ - uchar damage = widget->layout_damage (); - damage |= LAYOUT_XYWH; - widget->layout_damage (damage); + widget->resize (translateCanvasXToViewX (allocation->x), + translateCanvasYToViewY (allocation->y), + allocation->width, + allocation->ascent + allocation->descent); } -void FltkWidgetView::drawFltkWidget (::fltk::Widget *widget, +void FltkWidgetView::drawFltkWidget (Fl_Widget *widget, core::Rectangle *area) { draw_child (*widget); + draw_outside_label(*widget); } } // namespace fltk diff --git a/dw/fltkviewbase.hh b/dw/fltkviewbase.hh index b5c3ab5e..2b248803 100644 --- a/dw/fltkviewbase.hh +++ b/dw/fltkviewbase.hh @@ -4,45 +4,58 @@ #include <time.h> // for time_t #include <sys/time.h> // for time_t in FreeBSD -#include <fltk/Group.h> -#include <fltk/Image.h> -#include <fltk/Scrollbar.h> +#include <FL/Fl_Group.H> +#include <FL/x.H> #include "fltkcore.hh" namespace dw { namespace fltk { -class FltkViewBase: public FltkView, public ::fltk::Group +class FltkViewBase: public FltkView, public Fl_Group { private: + class BackBuffer { + private: + int w; + int h; + bool created; + + public: + Fl_Offscreen offscreen; + + BackBuffer (); + ~BackBuffer (); + void setSize(int w, int h); + }; + typedef enum { DRAW_PLAIN, DRAW_CLIPPED, DRAW_BUFFERED } DrawType; int bgColor; core::Region drawRegion; - ::fltk::Rectangle *exposeArea; - static ::fltk::Image *backBuffer; + core::Rectangle *exposeArea; + static BackBuffer *backBuffer; static bool backBufferInUse; void draw (const core::Rectangle *rect, DrawType type); void drawChildWidgets (); inline void clipPoint (int *x, int *y, int border) { if (exposeArea) { - if (*x < exposeArea->x () - border) - *x = exposeArea->x () - border; - if (*x > exposeArea->r () + border) - *x = exposeArea->r () + border; - if (*y < exposeArea->y () - border) - *y = exposeArea->y () - border; - if (*y > exposeArea->b () + border) - *y = exposeArea->b () + border; + if (*x < exposeArea->x - border) + *x = exposeArea->x - border; + if (*x > exposeArea->x + exposeArea->width + border) + *x = exposeArea->x + exposeArea->width + border; + if (*y < exposeArea->y - border) + *y = exposeArea->y - border; + if (*y > exposeArea->y + exposeArea->height + border) + *y = exposeArea->y + exposeArea->height + border; } } - protected: core::Layout *theLayout; int canvasWidth, canvasHeight; int mouse_x, mouse_y; + Fl_Widget *focused_child; virtual int translateViewXToCanvasX (int x) = 0; virtual int translateViewYToCanvasY (int y) = 0; @@ -85,7 +98,8 @@ public: int angle1, int angle2); void drawPolygon (core::style::Color *color, core::style::Color::Shading shading, - bool filled, int points[][2], int npoints); + bool filled, bool convex, + core::Point *points, int npoints); core::View *getClippingView (int x, int y, int width, int height); void mergeClippingView (core::View *clippingView); @@ -99,21 +113,24 @@ public: FltkWidgetView (int x, int y, int w, int h, const char *label = 0); ~FltkWidgetView (); - void layout(); - void drawText (core::style::Font *font, core::style::Color *color, core::style::Color::Shading shading, int x, int y, const char *text, int len); + void drawSimpleWrappedText (core::style::Font *font, + core::style::Color *color, + core::style::Color::Shading shading, + int x, int y, int w, int h, + const char *text); void drawImage (core::Imgbuf *imgbuf, int xRoot, int yRoot, int x, int y, int width, int height); bool usesFltkWidgets (); - void addFltkWidget (::fltk::Widget *widget, core::Allocation *allocation); - void removeFltkWidget (::fltk::Widget *widget); - void allocateFltkWidget (::fltk::Widget *widget, + void addFltkWidget (Fl_Widget *widget, core::Allocation *allocation); + void removeFltkWidget (Fl_Widget *widget); + void allocateFltkWidget (Fl_Widget *widget, core::Allocation *allocation); - void drawFltkWidget (::fltk::Widget *widget, core::Rectangle *area); + void drawFltkWidget (Fl_Widget *widget, core::Rectangle *area); }; } // namespace fltk diff --git a/dw/fltkviewport.cc b/dw/fltkviewport.cc index a8555c60..19e28854 100644 --- a/dw/fltkviewport.cc +++ b/dw/fltkviewport.cc @@ -21,14 +21,13 @@ #include "fltkviewport.hh" -#include <fltk/draw.h> -#include <fltk/damage.h> -#include <fltk/events.h> +#include <FL/Fl.H> +#include <FL/fl_draw.H> +#include <FL/names.h> #include <stdio.h> #include "../lout/msg.h" -using namespace fltk; using namespace lout; using namespace lout::object; using namespace lout::container::typed; @@ -36,21 +35,39 @@ using namespace lout::container::typed; namespace dw { namespace fltk { -FltkViewport::FltkViewport (int x, int y, int w, int h, const char *label): - FltkWidgetView (x, y, w, h, label) +/* + * Lets SHIFT+{Left,Right} go to the parent + */ +class CustScrollbar : public Fl_Scrollbar { - hscrollbar = new Scrollbar (0, 0, 1, 1); - hscrollbar->set_horizontal(); +public: + CustScrollbar(int x, int y, int w, int h) : Fl_Scrollbar(x,y,w,h) {}; + int handle(int e) { + if (e == FL_SHORTCUT && Fl::event_state() == FL_SHIFT && + (Fl::event_key() == FL_Left || Fl::event_key() == FL_Right)) + return 0; + return Fl_Scrollbar::handle(e); + } +}; + +FltkViewport::FltkViewport (int X, int Y, int W, int H, const char *label): + FltkWidgetView (X, Y, W, H, label) +{ + hscrollbar = new CustScrollbar (x (), y (), 1, 1); + hscrollbar->type(FL_HORIZONTAL); hscrollbar->callback (hscrollbarCallback, this); + hscrollbar->hide(); add (hscrollbar); - vscrollbar = new Scrollbar (0, 0, 1, 1); - vscrollbar->set_vertical(); + vscrollbar = new Fl_Scrollbar (x (), y(), 1, 1); + vscrollbar->type(FL_VERTICAL); vscrollbar->callback (vscrollbarCallback, this); + vscrollbar->hide(); add (vscrollbar); + hasDragScroll = 1; scrollX = scrollY = scrollDX = scrollDY = 0; - dragScrolling = 0; + horScrolling = verScrolling = dragScrolling = 0; gadgetOrientation[0] = GADGET_HORIZONTAL; gadgetOrientation[1] = GADGET_HORIZONTAL; @@ -58,7 +75,7 @@ FltkViewport::FltkViewport (int x, int y, int w, int h, const char *label): gadgetOrientation[3] = GADGET_HORIZONTAL; gadgets = - new container::typed::List <object::TypedPointer < ::fltk::Widget> > + new container::typed::List <object::TypedPointer < Fl_Widget> > (true); } @@ -72,6 +89,7 @@ void FltkViewport::adjustScrollbarsAndGadgetsAllocation () int hdiff = 0, vdiff = 0; int visibility = 0; + _MSG(" >>FltkViewport::adjustScrollbarsAndGadgetsAllocation\n"); if (hscrollbar->visible ()) visibility |= 1; if (vscrollbar->visible ()) @@ -94,32 +112,25 @@ void FltkViewport::adjustScrollbarsAndGadgetsAllocation () vdiff = hscrollbar->visible () ? SCROLLBAR_THICKNESS : 0; } - hscrollbar->x (0); - hscrollbar->y (0 + h () - SCROLLBAR_THICKNESS); - hscrollbar->w (w () - hdiff); - hscrollbar->h (SCROLLBAR_THICKNESS); - - vscrollbar->x (0 + w () - SCROLLBAR_THICKNESS); - vscrollbar->y (0); - vscrollbar->h (h () - vdiff); - vscrollbar->w (SCROLLBAR_THICKNESS); + hscrollbar->resize(x (), y () + h () - SCROLLBAR_THICKNESS, + w () - hdiff, SCROLLBAR_THICKNESS); + vscrollbar->resize(x () + w () - SCROLLBAR_THICKNESS, y (), + SCROLLBAR_THICKNESS, h () - vdiff); - int x = w () - SCROLLBAR_THICKNESS, y = h () - SCROLLBAR_THICKNESS; - for (Iterator <TypedPointer < ::fltk::Widget> > it = gadgets->iterator (); + int X = x () + w () - SCROLLBAR_THICKNESS; + int Y = y () + h () - SCROLLBAR_THICKNESS; + for (Iterator <TypedPointer < Fl_Widget> > it = gadgets->iterator (); it.hasNext (); ) { - ::fltk::Widget *widget = it.getNext()->getTypedValue (); - widget->x (0); - widget->y (0); - widget->w (SCROLLBAR_THICKNESS); - widget->h (SCROLLBAR_THICKNESS); + Fl_Widget *widget = it.getNext()->getTypedValue (); + widget->resize(x (), y (), SCROLLBAR_THICKNESS, SCROLLBAR_THICKNESS); switch (gadgetOrientation [visibility]) { case GADGET_VERTICAL: - y -= SCROLLBAR_THICKNESS; + Y -= SCROLLBAR_THICKNESS; break; case GADGET_HORIZONTAL: - x -= SCROLLBAR_THICKNESS; + X -= SCROLLBAR_THICKNESS; break; } } @@ -141,40 +152,43 @@ void FltkViewport::vscrollbarChanged () scroll (0, vscrollbar->value () - scrollY); } -void FltkViewport::vscrollbarCallback (Widget *vscrollbar, void *viewportPtr) +void FltkViewport::vscrollbarCallback (Fl_Widget *vscrollbar,void *viewportPtr) { ((FltkViewport*)viewportPtr)->vscrollbarChanged (); } -void FltkViewport::hscrollbarCallback (Widget *hscrollbar, void *viewportPtr) +void FltkViewport::hscrollbarCallback (Fl_Widget *hscrollbar,void *viewportPtr) { ((FltkViewport*)viewportPtr)->hscrollbarChanged (); } // ---------------------------------------------------------------------- -void FltkViewport::layout () +void FltkViewport::resize(int X, int Y, int W, int H) { - theLayout->viewportSizeChanged (this, w(), h()); - adjustScrollbarsAndGadgetsAllocation (); + bool dimension_changed = W != w() || H != h(); - FltkWidgetView::layout (); + Fl_Group::resize(X, Y, W, H); + if (dimension_changed) { + theLayout->viewportSizeChanged (this, W, H); + adjustScrollbarsAndGadgetsAllocation (); + } } -void FltkViewport::draw_area (void *data, const Rectangle& cr ) +void FltkViewport::draw_area (void *data, int x, int y, int w, int h) { FltkViewport *vp = (FltkViewport*) data; - push_clip(cr); + fl_push_clip(x, y, w, h); vp->FltkWidgetView::draw (); - for (Iterator <TypedPointer < ::fltk::Widget> > it = vp->gadgets->iterator(); + for (Iterator <TypedPointer < Fl_Widget> > it = vp->gadgets->iterator(); it.hasNext (); ) { - ::fltk::Widget *widget = it.getNext()->getTypedValue (); + Fl_Widget *widget = it.getNext()->getTypedValue (); vp->draw_child (*widget); } - pop_clip(); + fl_pop_clip(); } @@ -182,20 +196,19 @@ void FltkViewport::draw () { int hdiff = vscrollbar->visible () ? SCROLLBAR_THICKNESS : 0; int vdiff = hscrollbar->visible () ? SCROLLBAR_THICKNESS : 0; - Rectangle cr (0, 0, w () - hdiff, h () - vdiff); int d = damage(); - if (d & DAMAGE_SCROLL) { - set_damage (DAMAGE_SCROLL); - scrollrect(cr, -scrollDX, -scrollDY, draw_area, this); - d &= ~DAMAGE_SCROLL; - set_damage (d); + if (d & FL_DAMAGE_SCROLL) { + clear_damage (FL_DAMAGE_SCROLL); + fl_scroll(x(), y(), w() - hdiff, h() - vdiff, + -scrollDX, -scrollDY, draw_area, this); + clear_damage (d & ~FL_DAMAGE_SCROLL); } if (d) { - draw_area(this, cr); + draw_area(this, x(), y(), w () - hdiff, h () - vdiff); - if (d == DAMAGE_CHILD) { + if (d == FL_DAMAGE_CHILD) { if (hscrollbar->damage ()) draw_child (*hscrollbar); if (vscrollbar->damage ()) @@ -212,89 +225,93 @@ void FltkViewport::draw () int FltkViewport::handle (int event) { - _MSG("FltkViewport::handle %d\n", event); - - if (hscrollbar->Rectangle::contains (event_x (), event_y ()) && - !(event_state() & (SHIFT | CTRL | ALT)) && - hscrollbar->send (event)) { - return 1; - } - - if (vscrollbar->Rectangle::contains (event_x (), event_y ()) && - vscrollbar->send (event)) { - return 1; - } + _MSG("FltkViewport::handle %s\n", fl_eventnames[event]); switch(event) { - case ::fltk::KEY: - /* Tell fltk we want to receive KEY events as SHORTCUT. - * As we don't know the exact keybindings set by the user, we ask - * for all of them (except TabKey to keep form navigation). */ - if (::fltk::event_key() != TabKey) + case FL_KEYBOARD: + /* When the viewport has focus (and not one of its children), FLTK + * sends the event here. Returning zero tells FLTK to resend the + * event as SHORTCUT, which we finally route to the parent. */ + + /* As we don't know the exact keybindings set by the user, we ask + * for all of them (except Tab to keep form navigation). */ + if (Fl::event_key() != FL_Tab) return 0; break; - case ::fltk::FOCUS: - /** \bug Draw focus box. */ + case FL_SHORTCUT: + /* send it to the parent (UI) */ + return 0; - /* If the user clicks with the left button we take focus - * and thereby unfocus any form widgets. - * Otherwise we let fltk do the focus handling. - */ - if (::fltk::event_button() == ::fltk::LeftButton || focus_index() < 0) { - focus_index(-1); - return 1; - } + case FL_FOCUS: + /** \bug Draw focus box. */ break; - case ::fltk::UNFOCUS: + case FL_UNFOCUS: /** \bug Undraw focus box. */ break; - case ::fltk::PUSH: - take_focus(); - if (::fltk::event_button() == ::fltk::MiddleButton) { - /* pass event so that middle click can open link in new window */ - if (FltkWidgetView::handle (event) == 0) { + case FL_PUSH: + if (vscrollbar->visible() && Fl::event_inside(vscrollbar)) { + if (vscrollbar->handle(event)) + verScrolling = 1; + } else if (hscrollbar->visible() && Fl::event_inside(hscrollbar)) { + if (hscrollbar->handle(event)) + horScrolling = 1; + } else if (FltkWidgetView::handle(event) == 0 && + Fl::event_button() == FL_MIDDLE_MOUSE) { + if (!hasDragScroll) { + /* let the parent widget handle it... */ + return 0; + } else { + /* receive FL_DRAG and FL_RELEASE */ dragScrolling = 1; - dragX = ::fltk::event_x(); - dragY = ::fltk::event_y(); + dragX = Fl::event_x(); + dragY = Fl::event_y(); setCursor (core::style::CURSOR_MOVE); } - return 1; } + return 1; break; - case ::fltk::DRAG: - if (::fltk::event_button() == ::fltk::MiddleButton) { - if (dragScrolling) { - scroll(dragX - ::fltk::event_x(), dragY - ::fltk::event_y()); - dragX = ::fltk::event_x(); - dragY = ::fltk::event_y(); - return 1; - } + case FL_DRAG: + if (dragScrolling && Fl::event_button() == FL_MIDDLE_MOUSE) { + scroll(dragX - Fl::event_x(), dragY - Fl::event_y()); + dragX = Fl::event_x(); + dragY = Fl::event_y(); + return 1; + } else if (verScrolling) { + vscrollbar->handle(event); + return 1; + } else if (horScrolling) { + hscrollbar->handle(event); + return 1; } break; - case ::fltk:: MOUSEWHEEL: - return (event_dx() ? hscrollbar : vscrollbar)->handle(event); + case FL_MOUSEWHEEL: + return (Fl::event_dx() ? hscrollbar : vscrollbar)->handle(event); break; - case ::fltk::RELEASE: - if (::fltk::event_button() == ::fltk::MiddleButton) { - dragScrolling = 0; + case FL_RELEASE: + if (Fl::event_button() == FL_MIDDLE_MOUSE) { setCursor (core::style::CURSOR_DEFAULT); + } else if (verScrolling) { + vscrollbar->handle(event); + } else if (horScrolling) { + hscrollbar->handle(event); } + horScrolling = verScrolling = dragScrolling = 0; break; - case ::fltk::ENTER: + case FL_ENTER: /* could be the result of, e.g., closing another window. */ - mouse_x = ::fltk::event_x(); - mouse_y = ::fltk::event_y(); + mouse_x = Fl::event_x(); + mouse_y = Fl::event_y(); positionChanged(); break; - case ::fltk::LEAVE: + case FL_LEAVE: mouse_x = mouse_y = -1; break; } @@ -315,7 +332,7 @@ void FltkViewport::setCanvasSize (int width, int ascent, int descent) */ void FltkViewport::positionChanged () { - if (mouse_x != -1) + if (mouse_x != -1 && dragScrolling == false) (void)theLayout->motionNotify (this, translateViewXToCanvasX (mouse_x), translateViewYToCanvasY (mouse_y), @@ -324,7 +341,7 @@ void FltkViewport::positionChanged () /* * For scrollbars, this currently sets the same step to both vertical and - * horizontal. It may me differentiated if necessary. + * horizontal. It may be differentiated if necessary. */ void FltkViewport::setScrollStep(int step) { @@ -373,7 +390,7 @@ void FltkViewport::scrollTo (int x, int y) scrollY = y; adjustScrollbarValues (); - redraw (DAMAGE_SCROLL); + damage(FL_DAMAGE_SCROLL); theLayout->scrollPosChanged (this, scrollX, scrollY); positionChanged(); } @@ -386,9 +403,13 @@ void FltkViewport::scroll (int dx, int dy) void FltkViewport::scroll (core::ScrollCommand cmd) { if (cmd == core::SCREEN_UP_CMD) { - scroll (0, -vscrollbar->pagesize ()); + scroll (0, -h () + vscrollbar->linesize ()); } else if (cmd == core::SCREEN_DOWN_CMD) { - scroll (0, vscrollbar->pagesize ()); + scroll (0, h () - vscrollbar->linesize ()); + } else if (cmd == core::SCREEN_LEFT_CMD) { + scroll (-w() + hscrollbar->linesize (), 0); + } else if (cmd == core::SCREEN_RIGHT_CMD) { + scroll (w() - hscrollbar->linesize (), 0); } else if (cmd == core::LINE_UP_CMD) { scroll (0, (int) -vscrollbar->linesize ()); } else if (cmd == core::LINE_DOWN_CMD) { @@ -408,52 +429,59 @@ void FltkViewport::setViewportSize (int width, int height, int hScrollbarThickness, int vScrollbarThickness) { - if (hScrollbarThickness > 0) - hscrollbar->show (); - else - hscrollbar->hide (); - if (vScrollbarThickness > 0) - vscrollbar->show (); - else - vscrollbar->hide (); + int adjustReq = + (hscrollbar->visible() ? !hScrollbarThickness : hScrollbarThickness) || + (vscrollbar->visible() ? !vScrollbarThickness : vScrollbarThickness); + + _MSG("FltkViewport::setViewportSize old_w,old_h=%dx%d -> w,h=%dx%d\n" + "\t hThick=%d hVis=%d, vThick=%d vVis=%d, adjustReq=%d\n", + w(),h(),width,height, + hScrollbarThickness,hscrollbar->visible(), + vScrollbarThickness,vscrollbar->visible(), adjustReq); + + (hScrollbarThickness > 0) ? hscrollbar->show () : hscrollbar->hide (); + (vScrollbarThickness > 0) ? vscrollbar->show () : vscrollbar->hide (); /* If no scrollbar, go to the beginning */ scroll(hScrollbarThickness ? 0 : -scrollX, vScrollbarThickness ? 0 : -scrollY); + + /* Adjust when scrollbar visibility changes */ + if (adjustReq) + adjustScrollbarsAndGadgetsAllocation (); } void FltkViewport::updateCanvasWidgets (int dx, int dy) { // scroll all child widgets except scroll bars for (int i = children () - 1; i > 0; i--) { - ::fltk::Widget *widget = child (i); + Fl_Widget *widget = child (i); if (widget == hscrollbar || widget == vscrollbar) continue; - widget->x (widget->x () - dx); - widget->y (widget->y () - dy); + widget->position(widget->x () - dx, widget->y () - dy); } } -int FltkViewport::translateViewXToCanvasX (int x) +int FltkViewport::translateViewXToCanvasX (int X) { - return x + scrollX; + return X - x () + scrollX; } -int FltkViewport::translateViewYToCanvasY (int y) +int FltkViewport::translateViewYToCanvasY (int Y) { - return y + scrollY; + return Y - y () + scrollY; } -int FltkViewport::translateCanvasXToViewX (int x) +int FltkViewport::translateCanvasXToViewX (int X) { - return x - scrollX; + return X + x () - scrollX; } -int FltkViewport::translateCanvasYToViewY (int y) +int FltkViewport::translateCanvasYToViewY (int Y) { - return y - scrollY; + return Y + y () - scrollY; } // ---------------------------------------------------------------------- @@ -468,11 +496,11 @@ void FltkViewport::setGadgetOrientation (bool hscrollbarVisible, adjustScrollbarsAndGadgetsAllocation (); } -void FltkViewport::addGadget (::fltk::Widget *gadget) +void FltkViewport::addGadget (Fl_Widget *gadget) { /** \bug Reparent? */ - gadgets->append (new TypedPointer < ::fltk::Widget> (gadget)); + gadgets->append (new TypedPointer < Fl_Widget> (gadget)); adjustScrollbarsAndGadgetsAllocation (); } diff --git a/dw/fltkviewport.hh b/dw/fltkviewport.hh index 1e7f54f6..3df1dccb 100644 --- a/dw/fltkviewport.hh +++ b/dw/fltkviewport.hh @@ -1,8 +1,8 @@ #ifndef __DW_FLTKVIEWPORT_HH__ #define __DW_FLTKVIEWPORT_HH__ -#include <fltk/Group.h> -#include <fltk/Scrollbar.h> +#include <FL/Fl_Group.H> +#include <FL/Fl_Scrollbar.H> #include "core.hh" #include "fltkcore.hh" @@ -21,12 +21,13 @@ private: int scrollX, scrollY; int scrollDX, scrollDY; - int dragScrolling, dragX, dragY; + int hasDragScroll, dragScrolling, dragX, dragY; + int horScrolling, verScrolling; - ::fltk::Scrollbar *vscrollbar, *hscrollbar; + Fl_Scrollbar *vscrollbar, *hscrollbar; GadgetOrientation gadgetOrientation[4]; - lout::container::typed::List <lout::object::TypedPointer < ::fltk::Widget> > + lout::container::typed::List <lout::object::TypedPointer < Fl_Widget> > *gadgets; void adjustScrollbarsAndGadgetsAllocation (); @@ -35,11 +36,11 @@ private: void vscrollbarChanged (); void positionChanged (); - static void hscrollbarCallback (Widget *hscrollbar, void *viewportPtr); - static void vscrollbarCallback (Widget *vscrollbar, void *viewportPtr); + static void hscrollbarCallback (Fl_Widget *hscrollbar, void *viewportPtr); + static void vscrollbarCallback (Fl_Widget *vscrollbar, void *viewportPtr); void updateCanvasWidgets (int oldScrollX, int oldScrollY); - static void draw_area (void *data, const Rectangle& cr); + static void draw_area (void *data, int x, int y, int w, int h); protected: int translateViewXToCanvasX (int x); @@ -51,7 +52,7 @@ public: FltkViewport (int x, int y, int w, int h, const char *label = 0); ~FltkViewport (); - void layout(); + void resize(int x, int y, int w, int h); void draw (); int handle (int event); @@ -69,7 +70,8 @@ public: void setGadgetOrientation (bool hscrollbarVisible, bool vscrollbarVisible, GadgetOrientation gadgetOrientation); - void addGadget (::fltk::Widget *gadget); + void setDragScroll (bool enable) { hasDragScroll = enable ? 1 : 0; } + void addGadget (Fl_Widget *gadget); }; } // namespace fltk diff --git a/dw/image.cc b/dw/image.cc index cab40ed5..1cb9ce39 100644 --- a/dw/image.cc +++ b/dw/image.cc @@ -157,7 +157,7 @@ Image::Image(const char *altText) Image::~Image() { if (altText) - delete altText; + free(altText); if (buffer) buffer->unref (); if (mapKey) @@ -315,8 +315,8 @@ bool Image::buttonPressImpl (core::EventButton *event) { bool ret = false; - currLink = mapList? mapList->link (mapKey, contentX(event),contentY(event)): - getStyle()->x_link; + currLink = mapList ? mapList->link(mapKey,contentX(event),contentY(event)) : + getStyle()->x_link; if (event->button == 3){ (void)layout->emitLinkPress(this, currLink, getStyle()->x_img, -1, -1, event); @@ -330,7 +330,7 @@ bool Image::buttonPressImpl (core::EventButton *event) bool Image::buttonReleaseImpl (core::EventButton *event) { - currLink = mapList ? mapList->link (mapKey, contentX(event),contentY(event)): + currLink = mapList ? mapList->link(mapKey,contentX(event),contentY(event)) : getStyle()->x_link; if (clicking) { int x = isMap ? contentX(event) : -1; @@ -384,12 +384,11 @@ void Image::draw (core::View *view, core::Rectangle *area) getContentHeight()); } - usedView->drawText (getStyle()->font, getStyle()->color, + usedView->drawSimpleWrappedText (getStyle()->font, getStyle()->color, core::style::Color::SHADING_NORMAL, allocation.x + getStyle()->boxOffsetX (), - allocation.y + getStyle()->boxOffsetY () - + getStyle()->font->ascent, - altText, strlen(altText)); + allocation.y + getStyle()->boxOffsetY (), + getContentWidth(), getContentHeight(), altText); if (clippingView) view->mergeClippingView (clippingView); diff --git a/dw/layout.cc b/dw/layout.cc index 8f67e895..d2610687 100644 --- a/dw/layout.cc +++ b/dw/layout.cc @@ -174,7 +174,7 @@ bool Layout::LinkEmitter::emitClick (Widget *widget, int link, int img, Layout::Anchor::~Anchor () { - delete name; + free(name); } // --------------------------------------------------------------------- @@ -194,6 +194,7 @@ Layout::Layout (Platform *platform) canvasWidth = canvasAscent = canvasDescent = 0; usesViewport = false; + drawAfterScrollReq = false; scrollX = scrollY = 0; viewportWidth = viewportHeight = 0; hScrollbarThickness = vScrollbarThickness = 0; @@ -219,14 +220,19 @@ Layout::Layout (Platform *platform) Layout::~Layout () { + widgetAtPoint = NULL; + if (scrollIdleId != -1) platform->removeIdle (scrollIdleId); if (resizeIdleId != -1) platform->removeIdle (resizeIdleId); if (bgColor) bgColor->unref (); - if (topLevel) - delete topLevel; + if (topLevel) { + Widget *w = topLevel; + topLevel = NULL; + delete w; + } delete platform; delete view; delete anchorsTable; @@ -279,9 +285,12 @@ void Layout::removeWidget () void Layout::setWidget (Widget *widget) { - if (topLevel) - delete topLevel; widgetAtPoint = NULL; + if (topLevel) { + Widget *w = topLevel; + topLevel = NULL; + delete w; + } textZone->zoneFree (); addWidget (widget); @@ -449,6 +458,10 @@ void Layout::scrollIdle () if (xChanged || yChanged) { adjustScrollPos (); view->scrollTo (scrollX, scrollY); + if (drawAfterScrollReq) { + drawAfterScrollReq = false; + view->queueDrawTotal (); + } } scrollIdleId = -1; @@ -496,7 +509,11 @@ void Layout::draw (View *view, Rectangle *area) { Rectangle widgetArea, intersection, widgetDrawArea; - if (topLevel) { + if (scrollIdleId != -1) { + /* scroll is pending, defer draw until after scrollIdle() */ + drawAfterScrollReq = true; + + } else if (topLevel) { /* Draw the top level widget. */ widgetArea.x = topLevel->allocation.x; widgetArea.y = topLevel->allocation.y; @@ -527,7 +544,7 @@ void Layout::setAnchor (const char *anchor) _MSG("setAnchor (%s)\n", anchor); if (requestedAnchor) - delete requestedAnchor; + free(requestedAnchor); requestedAnchor = anchor ? strdup (anchor) : NULL; updateAnchor (); } @@ -672,10 +689,9 @@ void Layout::resizeIdle () } // Set viewport sizes. - if (view->usesViewport ()) - view->setViewportSize (viewportWidth, viewportHeight, - actualHScrollbarThickness, - actualVScrollbarThickness); + view->setViewportSize (viewportWidth, viewportHeight, + actualHScrollbarThickness, + actualVScrollbarThickness); } } @@ -691,7 +707,7 @@ void Layout::setSizeHints () if (topLevel) { topLevel->setWidth (viewportWidth - (canvasHeightGreater ? vScrollbarThickness : 0)); - topLevel->setAscent (viewportHeight - vScrollbarThickness); + topLevel->setAscent (viewportHeight - hScrollbarThickness); topLevel->setDescent (0); } } @@ -808,6 +824,7 @@ void Layout::enterNotify (View *view, int x, int y, ButtonState state) */ void Layout::leaveNotify (View *view, ButtonState state) { +#if 0 Widget *lastWidget; EventCrossing event; @@ -820,6 +837,9 @@ void Layout::leaveNotify (View *view, ButtonState state) event.currentWidget = widgetAtPoint; lastWidget->leaveNotify (&event); } +#else + moveOutOfView (state); +#endif } /* @@ -838,15 +858,16 @@ Widget *Layout::getWidgetAtPoint (int x, int y) /* * Emit the necessary crossing events, when the mouse pointer has moved to - * the given widget. + * the given widget (by mouse or scrolling). */ void Layout::moveToWidget (Widget *newWidgetAtPoint, ButtonState state) { Widget *ancestor, *w; Widget **track; - int trackLen, i; + int trackLen, i, i_a; EventCrossing crossingEvent; + _MSG("moveToWidget: wap=%p nwap=%p\n",widgetAtPoint,newWidgetAtPoint); if (newWidgetAtPoint != widgetAtPoint) { // The mouse pointer has been moved into another widget. if (newWidgetAtPoint && widgetAtPoint) @@ -875,6 +896,7 @@ void Layout::moveToWidget (Widget *newWidgetAtPoint, ButtonState state) /* first part */ for (w = widgetAtPoint; w != ancestor; w = w->getParent ()) track[i++] = w; + i_a = i; track[i++] = ancestor; if (newWidgetAtPoint) { /* second part */ @@ -882,17 +904,32 @@ void Layout::moveToWidget (Widget *newWidgetAtPoint, ButtonState state) for (w = newWidgetAtPoint; w != ancestor; w = w->getParent ()) track[i--] = w; } - - /* Send events to all events on the track */ +#if 0 + MSG("Track: %s[ ", widgetAtPoint ? "" : "nil "); + for (i = 0; i < trackLen; i++) + MSG("%s%p ", i == i_a ? ">" : "", track[i]); + MSG("] %s\n", newWidgetAtPoint ? "" : "nil"); +#endif + + /* Send events to the widgets on the track */ for (i = 0; i < trackLen; i++) { crossingEvent.state = state; crossingEvent.currentWidget = widgetAtPoint; // ??? crossingEvent.lastWidget = widgetAtPoint; // ??? - - if (i != 0) - track[i]->enterNotify (&crossingEvent); - if (i != trackLen - 1) + if (i < i_a) { track[i]->leaveNotify (&crossingEvent); + } else if (i == i_a) { /* ancestor */ + /* Don't touch ancestor unless: + * - moving into/from NULL, + * - ancestor becomes the newWidgetAtPoint */ + if (i_a == trackLen-1 && !newWidgetAtPoint) + track[i]->leaveNotify (&crossingEvent); + else if ((i_a == 0 && !widgetAtPoint) || + (i_a == trackLen-1 && newWidgetAtPoint)) + track[i]->enterNotify (&crossingEvent); + } else { + track[i]->enterNotify (&crossingEvent); + } } delete[] track; diff --git a/dw/layout.hh b/dw/layout.hh index dc9bf227..d08eb363 100644 --- a/dw/layout.hh +++ b/dw/layout.hh @@ -138,7 +138,7 @@ private: style::Cursor cursor; int canvasWidth, canvasAscent, canvasDescent; - bool usesViewport; + bool usesViewport, drawAfterScrollReq; int scrollX, scrollY, viewportWidth, viewportHeight; bool canvasHeightGreater; int hScrollbarThickness, vScrollbarThickness; @@ -152,7 +152,8 @@ private: bool scrollIdleNotInterrupted; /* Anchors of the widget tree */ - lout::container::typed::HashTable <lout::object::String, Anchor> *anchorsTable; + lout::container::typed::HashTable <lout::object::String, Anchor> + *anchorsTable; SelectionState selectionState; FindtextState findtextState; @@ -336,6 +337,11 @@ public: return platform->createTooltip (text); } + inline void cancelTooltip () + { + return platform->cancelTooltip (); + } + inline Imgbuf *createImgbuf (Imgbuf::Type type, int width, int height) { return platform->createImgbuf (type, width, height); diff --git a/dw/platform.hh b/dw/platform.hh index 69d1feab..b79b5346 100644 --- a/dw/platform.hh +++ b/dw/platform.hh @@ -131,6 +131,11 @@ public: */ virtual style::Tooltip *createTooltip (const char *text) = 0; + /** + * \brief Cancel a tooltip (either shown or requested) + */ + virtual void cancelTooltip () = 0; + /* * -------------------- * Image Buffers diff --git a/dw/selection.cc b/dw/selection.cc index 275eddaa..1552e80e 100644 --- a/dw/selection.cc +++ b/dw/selection.cc @@ -60,17 +60,6 @@ SelectionState::~SelectionState () reset (); } - -bool SelectionState::DoubleClickEmitter::emitToReceiver (lout::signal::Receiver - *receiver, - int signalNo, - int argc, - Object **argv) -{ - ((DoubleClickReceiver*)receiver)->doubleClick (); - return false; -} - void SelectionState::reset () { resetSelection (); @@ -98,81 +87,64 @@ void SelectionState::resetLink () } bool SelectionState::buttonPress (Iterator *it, int charPos, int linkNo, - EventButton *event, bool withinContent) + EventButton *event) { Widget *itWidget = it->getWidget (); bool ret = false; - if (event && event->button == 1 && - !withinContent && event->numPressed == 2) { - // When the user double-clicks on empty parts, emit the double click - // signal instead of normal processing. Used for full screen - // mode. - doubleClickEmitter.emitDoubleClick (); - // Reset everything, so that dw::core::Selection::buttonRelease will - // ignore the "release" event following soon. - highlight (false, 0); - reset (); + if (!event) return ret; + + if (event->button == 3) { + // menu popup + layout->emitLinkPress (itWidget, linkNo, -1, -1, -1, event); ret = true; - } else { - if (linkNo != -1) { - // link handling - if (event) { - (void) layout->emitLinkPress (itWidget, linkNo, -1, -1, -1, event); - resetLink (); - linkState = LINK_PRESSED; - linkButton = event->button; - DeepIterator *newLink = new DeepIterator (it); - if (newLink->isEmpty ()) { - delete newLink; - resetLink (); - } else { - link = newLink; - // It may be that the user has pressed on something activatable - // (linkNo != -1), but there is no contents, e.g. with images - // without ALTernative text. - if (link) { - linkChar = correctCharPos (link, charPos); - linkNumber = linkNo; - } - } - // We do not return the value of the signal method, - // but we do actually process this event. - ret = true; - } + } else if (linkNo != -1) { + // link handling + (void) layout->emitLinkPress (itWidget, linkNo, -1, -1, -1, event); + resetLink (); + linkState = LINK_PRESSED; + linkButton = event->button; + DeepIterator *newLink = new DeepIterator (it); + if (newLink->isEmpty ()) { + delete newLink; + resetLink (); } else { - // normal selection handling - if (event && event->button == 1) { - highlight (false, 0); - resetSelection (); - - selectionState = SELECTING; - DeepIterator *newFrom = new DeepIterator (it); - if (newFrom->isEmpty ()) { - delete newFrom; - resetSelection (); - } else { - from = newFrom; - fromChar = correctCharPos (from, charPos); - to = from->cloneDeepIterator (); - toChar = correctCharPos (to, charPos); - } - ret = true; - } else { - if (event && event->button == 3) { - // menu popup - layout->emitLinkPress (itWidget, -1, -1, -1, -1, event); - ret = true; - } + link = newLink; + // It may be that the user has pressed on something activatable + // (linkNo != -1), but there is no contents, e.g. with images + // without ALTernative text. + if (link) { + linkChar = correctCharPos (link, charPos); + linkNumber = linkNo; } } + // We do not return the value of the signal method, + // but we do actually process this event. + ret = true; + } else if (event->button == 1) { + // normal selection handling + highlight (false, 0); + resetSelection (); + + selectionState = SELECTING; + DeepIterator *newFrom = new DeepIterator (it); + if (newFrom->isEmpty ()) { + delete newFrom; + resetSelection (); + } else { + from = newFrom; + fromChar = correctCharPos (from, charPos); + to = from->cloneDeepIterator (); + toChar = correctCharPos (to, charPos); + } + ret = true; } return ret; } bool SelectionState::buttonRelease (Iterator *it, int charPos, int linkNo, - EventButton *event, bool withinContent) + EventButton *event) { Widget *itWidget = it->getWidget (); bool ret = false; @@ -214,7 +186,7 @@ bool SelectionState::buttonRelease (Iterator *it, int charPos, int linkNo, } bool SelectionState::buttonMotion (Iterator *it, int charPos, int linkNo, - EventMotion *event, bool withinContent) + EventMotion *event) { if (linkState == LINK_PRESSED) { //link handling @@ -238,21 +210,17 @@ bool SelectionState::buttonMotion (Iterator *it, int charPos, int linkNo, */ bool SelectionState::handleEvent (EventType eventType, Iterator *it, int charPos, int linkNo, - MousePositionEvent *event, - bool withinContent) + MousePositionEvent *event) { switch (eventType) { case BUTTON_PRESS: - return buttonPress (it, charPos, linkNo, (EventButton*)event, - withinContent); + return buttonPress (it, charPos, linkNo, (EventButton*)event); case BUTTON_RELEASE: - return buttonRelease (it, charPos, linkNo, (EventButton*)event, - withinContent); + return buttonRelease (it, charPos, linkNo, (EventButton*)event); case BUTTON_MOTION: - return buttonMotion (it, charPos, linkNo, (EventMotion*)event, - withinContent); + return buttonMotion (it, charPos, linkNo, (EventMotion*)event); default: @@ -334,7 +302,7 @@ void SelectionState::adjustSelection (Iterator *it, int charPos) } } else { if (cmpOld * cmpDiff < 0) { - // The user has reduced the selection. Unighlight the difference. + // The user has reduced the selection. Unhighlight the difference. highlight0 (false, to, 0, newTo, 0, cmpDiff); } diff --git a/dw/selection.hh b/dw/selection.hh index ba03fd18..7f6b1a58 100644 --- a/dw/selection.hh +++ b/dw/selection.hh @@ -44,10 +44,6 @@ namespace core { * otherwise -1 * <tr><td>dw::core::EventButton *event <td>the event itself; only the button * is used - * <tr><td>bool withinContent <td>true, if there is some selectable - * content unter the mouse cursor; if - * set to false, the "full screen" - * feature is used on double click. * </table> * * Look also at dw::core::SelectionState::handleEvent, which may be useful @@ -184,31 +180,7 @@ class SelectionState public: enum { END_OF_WORD = 1 << 30 }; - class DoubleClickReceiver: public lout::signal::Receiver - { - public: - virtual void doubleClick () = 0; - }; - private: - class DoubleClickEmitter: public lout::signal::Emitter - { - private: - enum { DOUBLE_CLICK }; - - protected: - bool emitToReceiver (lout::signal::Receiver *receiver, int signalNo, - int argc, Object **argv); - - public: - inline void connectDoubleClick (DoubleClickReceiver *receiver) - { connect (receiver); } - - inline void emitDoubleClick () { emitVoid (DOUBLE_CLICK, 0, NULL); } - }; - - DoubleClickEmitter doubleClickEmitter; - Layout *layout; // selection @@ -252,19 +224,15 @@ public: inline void setLayout (Layout *layout) { this->layout = layout; } void reset (); - inline void connectDoubleClick (DoubleClickReceiver *receiver) - { doubleClickEmitter.connectDoubleClick (receiver); } - bool buttonPress (Iterator *it, int charPos, int linkNo, - EventButton *event, bool withinContent); + EventButton *event); bool buttonRelease (Iterator *it, int charPos, int linkNo, - EventButton *event, bool withinContent); + EventButton *event); bool buttonMotion (Iterator *it, int charPos, int linkNo, - EventMotion *event, bool withinContent); + EventMotion *event); bool handleEvent (EventType eventType, Iterator *it, int charPos, - int linkNo, MousePositionEvent *event, - bool withinContent); + int linkNo, MousePositionEvent *event); }; } // namespace dw diff --git a/dw/style.cc b/dw/style.cc index ae0f4526..4276862a 100644 --- a/dw/style.cc +++ b/dw/style.cc @@ -431,7 +431,9 @@ static void drawBorderTop(View *view, Style *style, int x1, int y1, int x2, int y2) { - int points[4][2], d, w; + int d, w; + Point points[4]; + const bool filled = true, convex = true; bool ridge = false, inset = false, dotted = false; Color::Shading shading = Color::SHADING_NORMAL; @@ -460,35 +462,38 @@ static void drawBorderTop(View *view, Style *style, if (style->borderWidth.top == 1) { view->drawLine(style->borderColor.top, shading, x1, y1, x2, y2); } else { - points[0][0] = x1; - points[1][0] = x2 + 1; - points[0][1] = points[1][1] = y1; - points[2][0] = points[1][0] - style->borderWidth.right; - points[3][0] = x1 + style->borderWidth.left; - points[2][1] = points[3][1] = points[0][1] + style->borderWidth.top; - view->drawPolygon (style->borderColor.top, shading, true, points, 4); + points[0].x = x1; + points[1].x = x2 + 1; + points[0].y = points[1].y = y1; + points[2].x = points[1].x - style->borderWidth.right; + points[3].x = x1 + style->borderWidth.left; + points[2].y = points[3].y = points[0].y + style->borderWidth.top; + view->drawPolygon (style->borderColor.top, shading, filled, convex, + points, 4); } break; case BORDER_RIDGE: ridge = true; case BORDER_GROOVE: d = style->borderWidth.top & 1; - points[0][0] = x1; - points[1][0] = x2 + 1; - points[0][1] = points[1][1] = y1; - points[2][0] = x2 - style->borderWidth.right / 2; - points[3][0] = x1 + style->borderWidth.left / 2; - points[2][1] = points[3][1] = y1 + style->borderWidth.top / 2 + d; + points[0].x = x1; + points[1].x = x2 + 1; + points[0].y = points[1].y = y1; + points[2].x = x2 - style->borderWidth.right / 2; + points[3].x = x1 + style->borderWidth.left / 2; + points[2].y = points[3].y = y1 + style->borderWidth.top / 2 + d; shading = (ridge) ? Color::SHADING_LIGHT : Color::SHADING_DARK; - view->drawPolygon (style->borderColor.top, shading, true, points, 4); - points[0][0] = x1 + style->borderWidth.left / 2 + d; - points[1][0] = x2 - style->borderWidth.right / 2 + 1 - d; - points[0][1] = points[1][1] = y1 + style->borderWidth.top / 2 + d; - points[2][0] = x2 - style->borderWidth.right + 1 - d; - points[3][0] = x1 + style->borderWidth.left; - points[2][1] = points[3][1] = y1 + style->borderWidth.top; + view->drawPolygon (style->borderColor.top, shading, filled, convex, + points, 4); + points[0].x = x1 + style->borderWidth.left / 2 + d; + points[1].x = x2 - style->borderWidth.right / 2 + 1 - d; + points[0].y = points[1].y = y1 + style->borderWidth.top / 2 + d; + points[2].x = x2 - style->borderWidth.right + 1 - d; + points[3].x = x1 + style->borderWidth.left; + points[2].y = points[3].y = y1 + style->borderWidth.top; shading = (ridge) ? Color::SHADING_DARK : Color::SHADING_LIGHT; - view->drawPolygon (style->borderColor.top, shading, true, points, 4); + view->drawPolygon (style->borderColor.top, shading, filled, convex, + points, 4); break; case BORDER_DOUBLE: w = (int) rint(style->borderWidth.top / 3.0); @@ -499,20 +504,22 @@ static void drawBorderTop(View *view, Style *style, view->drawLine(style->borderColor.top, shading, x1, y1, x2, y2); break; } - points[0][0] = x1; - points[1][0] = x2 + 1; - points[0][1] = points[1][1] = y1; - points[2][0] = points[1][0] - w_r; - points[3][0] = points[0][0] + w_l; - points[2][1] = points[3][1] = points[0][1] + w; - view->drawPolygon (style->borderColor.top, shading, true, points, 4); - points[0][0] = x1 + style->borderWidth.left - w_l; - points[1][0] = x2 + 1 - style->borderWidth.right + w_r; - points[0][1] = points[1][1] = y1 + w + d; - points[2][0] = x2 + 1 - style->borderWidth.right; - points[3][0] = x1 + style->borderWidth.left; - points[2][1] = points[3][1] = y1 + style->borderWidth.top; - view->drawPolygon (style->borderColor.top, shading, true, points, 4); + points[0].x = x1; + points[1].x = x2 + 1; + points[0].y = points[1].y = y1; + points[2].x = points[1].x - w_r; + points[3].x = points[0].x + w_l; + points[2].y = points[3].y = points[0].y + w; + view->drawPolygon (style->borderColor.top, shading, filled, convex, + points, 4); + points[0].x = x1 + style->borderWidth.left - w_l; + points[1].x = x2 + 1 - style->borderWidth.right + w_r; + points[0].y = points[1].y = y1 + w + d; + points[2].x = x2 + 1 - style->borderWidth.right; + points[3].x = x1 + style->borderWidth.left; + points[2].y = points[3].y = y1 + style->borderWidth.top; + view->drawPolygon (style->borderColor.top, shading, filled, convex, + points, 4); break; } } @@ -521,7 +528,9 @@ static void drawBorderBottom(View *view, Style *style, int x1, int y1, int x2, int y2) { - int points[4][2], d, w; + int d, w; + Point points[4]; + const bool filled = true, convex = true; bool ridge = false, inset = false, dotted = false; Color::Shading shading = Color::SHADING_NORMAL; @@ -550,13 +559,14 @@ static void drawBorderBottom(View *view, Style *style, if (style->borderWidth.bottom == 1) { /* 1 pixel line */ view->drawLine(style->borderColor.bottom, shading, x1, y1, x2, y2); } else { - points[0][0] = x1 - 1; - points[1][0] = x2 + 2; - points[0][1] = points[1][1] = y1 + 1; - points[2][0] = points[1][0] - style->borderWidth.right; - points[3][0] = points[0][0] + style->borderWidth.left; - points[2][1] = points[3][1] = points[0][1]-style->borderWidth.bottom; - view->drawPolygon (style->borderColor.bottom, shading, true, points, 4); + points[0].x = x1 - 1; + points[1].x = x2 + 2; + points[0].y = points[1].y = y1 + 1; + points[2].x = points[1].x - style->borderWidth.right; + points[3].x = points[0].x + style->borderWidth.left; + points[2].y = points[3].y = points[0].y-style->borderWidth.bottom; + view->drawPolygon (style->borderColor.bottom, shading, filled, convex, + points, 4); } break; case BORDER_RIDGE: @@ -564,23 +574,25 @@ static void drawBorderBottom(View *view, Style *style, case BORDER_GROOVE: w = style->borderWidth.bottom; d = w & 1; - points[0][0] = x1 - 1; - points[1][0] = x2 + 2 - d; - points[0][1] = points[1][1] = y1 + 1; - points[2][0] = points[1][0] - style->borderWidth.right / 2; - points[3][0] = points[0][0] + style->borderWidth.left / 2 + d; - points[2][1] = points[3][1] = points[0][1] - w/2 - d; + points[0].x = x1 - 1; + points[1].x = x2 + 2 - d; + points[0].y = points[1].y = y1 + 1; + points[2].x = points[1].x - style->borderWidth.right / 2; + points[3].x = points[0].x + style->borderWidth.left / 2 + d; + points[2].y = points[3].y = points[0].y - w/2 - d; shading = (ridge) ? Color::SHADING_DARK : Color::SHADING_LIGHT; - view->drawPolygon (style->borderColor.bottom, shading, true, points, 4); + view->drawPolygon (style->borderColor.bottom, shading, filled, convex, + points, 4); // clockwise - points[0][0] = x1 + style->borderWidth.left - 1; - points[1][0] = x2 + 1 - style->borderWidth.right + 1; - points[0][1] = points[1][1] = y1 - w + 1; - points[2][0] = points[1][0] + style->borderWidth.right / 2; - points[3][0] = points[0][0] - style->borderWidth.left / 2; - points[2][1] = points[3][1] = points[0][1] + w/2; + points[0].x = x1 + style->borderWidth.left - 1; + points[1].x = x2 + 1 - style->borderWidth.right + 1; + points[0].y = points[1].y = y1 - w + 1; + points[2].x = points[1].x + style->borderWidth.right / 2; + points[3].x = points[0].x - style->borderWidth.left / 2; + points[2].y = points[3].y = points[0].y + w/2; shading = (ridge) ? Color::SHADING_LIGHT : Color::SHADING_DARK; - view->drawPolygon (style->borderColor.bottom, shading, true, points, 4); + view->drawPolygon (style->borderColor.bottom, shading, filled, convex, + points, 4); break; case BORDER_DOUBLE: w = (int) rint(style->borderWidth.bottom / 3.0); @@ -591,20 +603,22 @@ static void drawBorderBottom(View *view, Style *style, view->drawLine(style->borderColor.bottom, shading, x1, y1, x2, y2); break; } - points[0][0] = x2 + 2; - points[1][0] = x1 - 1; - points[0][1] = points[1][1] = y1 + 1; - points[2][0] = points[1][0] + w_l; - points[3][0] = points[0][0] - w_r; - points[2][1] = points[3][1] = points[0][1] - w; - view->drawPolygon (style->borderColor.bottom, shading, true, points, 4); - points[0][0] = x2 + 2 - style->borderWidth.right + w_r; - points[1][0] = x1 - 1 + style->borderWidth.left - w_l; - points[0][1] = points[1][1] = y1 + 1 - w - d; - points[2][0] = x1 - 1 + style->borderWidth.left; - points[3][0] = x2 + 2 - style->borderWidth.right; - points[2][1] = points[3][1] = y1 + 1 - style->borderWidth.bottom; - view->drawPolygon (style->borderColor.bottom, shading, true, points, 4); + points[0].x = x2 + 2; + points[1].x = x1 - 1; + points[0].y = points[1].y = y1 + 1; + points[2].x = points[1].x + w_l; + points[3].x = points[0].x - w_r; + points[2].y = points[3].y = points[0].y - w; + view->drawPolygon (style->borderColor.bottom, shading, filled, convex, + points, 4); + points[0].x = x2 + 2 - style->borderWidth.right + w_r; + points[1].x = x1 - 1 + style->borderWidth.left - w_l; + points[0].y = points[1].y = y1 + 1 - w - d; + points[2].x = x1 - 1 + style->borderWidth.left; + points[3].x = x2 + 2 - style->borderWidth.right; + points[2].y = points[3].y = y1 + 1 - style->borderWidth.bottom; + view->drawPolygon (style->borderColor.bottom, shading, filled, convex, + points, 4); break; } } @@ -613,7 +627,9 @@ static void drawBorderLeft(View *view, Style *style, int x1, int y1, int x2, int y2) { - int points[4][2], d, w; + int d, w; + Point points[4]; + bool filled = true, convex = true; bool ridge = false, inset = false, dotted = false; Color::Shading shading = Color::SHADING_NORMAL; @@ -641,13 +657,14 @@ static void drawBorderLeft(View *view, Style *style, if (style->borderWidth.left == 1) { /* 1 pixel line */ view->drawLine(style->borderColor.left, shading, x1, y1, x2, y2); } else { - points[0][0] = points[1][0] = x1; - points[0][1] = y1 - 1; - points[1][1] = y2 + 1; - points[2][0] = points[3][0] = points[0][0] + style->borderWidth.left; - points[2][1] = points[1][1] - style->borderWidth.bottom; - points[3][1] = points[0][1] + style->borderWidth.top; - view->drawPolygon (style->borderColor.left, shading, true, points, 4); + points[0].x = points[1].x = x1; + points[0].y = y1 - 1; + points[1].y = y2 + 1; + points[2].x = points[3].x = points[0].x + style->borderWidth.left; + points[2].y = points[1].y - style->borderWidth.bottom; + points[3].y = points[0].y + style->borderWidth.top; + view->drawPolygon (style->borderColor.left, shading, filled, convex, + points, 4); } break; case BORDER_RIDGE: @@ -655,22 +672,24 @@ static void drawBorderLeft(View *view, Style *style, case BORDER_GROOVE: w = style->borderWidth.left; d = w & 1; - points[0][0] = points[1][0] = x1; - points[0][1] = y1; - points[1][1] = y2; - points[2][0] = points[3][0] = x1 + w / 2 + d; - points[2][1] = y2 - style->borderWidth.bottom / 2; - points[3][1] = y1 + style->borderWidth.top / 2; + points[0].x = points[1].x = x1; + points[0].y = y1; + points[1].y = y2; + points[2].x = points[3].x = x1 + w / 2 + d; + points[2].y = y2 - style->borderWidth.bottom / 2; + points[3].y = y1 + style->borderWidth.top / 2; shading = (ridge) ? Color::SHADING_LIGHT : Color::SHADING_DARK; - view->drawPolygon (style->borderColor.left, shading, true, points, 4); - points[0][0] = points[1][0] = x1 + w / 2 + d; - points[0][1] = y1 + style->borderWidth.top / 2; - points[1][1] = y2 - style->borderWidth.bottom / 2; - points[2][0] = points[3][0] = x1 + w; - points[2][1] = y2 - style->borderWidth.bottom; - points[3][1] = y1 + style->borderWidth.top; + view->drawPolygon (style->borderColor.left, shading, filled, convex, + points, 4); + points[0].x = points[1].x = x1 + w / 2 + d; + points[0].y = y1 + style->borderWidth.top / 2; + points[1].y = y2 - style->borderWidth.bottom / 2; + points[2].x = points[3].x = x1 + w; + points[2].y = y2 - style->borderWidth.bottom; + points[3].y = y1 + style->borderWidth.top; shading = (ridge) ? Color::SHADING_DARK : Color::SHADING_LIGHT; - view->drawPolygon (style->borderColor.left, shading, true, points, 4); + view->drawPolygon (style->borderColor.left, shading, filled, convex, + points, 4); break; case BORDER_DOUBLE: w = (int) rint(style->borderWidth.left / 3.0); @@ -681,20 +700,22 @@ static void drawBorderLeft(View *view, Style *style, view->drawLine(style->borderColor.left, shading, x1, y1, x2, y2-1); break; } - points[0][0] = points[1][0] = x1; - points[0][1] = y1 - 1; - points[1][1] = y2 + 1; - points[2][0] = points[3][0] = points[0][0] + w; - points[2][1] = points[1][1] - w_b; - points[3][1] = points[0][1] + w_t; - view->drawPolygon (style->borderColor.left, shading, true, points, 4); - points[0][0] = points[1][0] = x1 + w + d; - points[0][1] = y1 - 1 + style->borderWidth.top - w_t; - points[1][1] = y2 + 1 - style->borderWidth.bottom + w_b; - points[2][0] = points[3][0] = points[0][0] + w; - points[2][1] = y2 + 1 - style->borderWidth.bottom; - points[3][1] = y1 - 1 + style->borderWidth.top; - view->drawPolygon (style->borderColor.left, shading, true, points, 4); + points[0].x = points[1].x = x1; + points[0].y = y1 - 1; + points[1].y = y2 + 1; + points[2].x = points[3].x = points[0].x + w; + points[2].y = points[1].y - w_b; + points[3].y = points[0].y + w_t; + view->drawPolygon (style->borderColor.left, shading, filled, convex, + points, 4); + points[0].x = points[1].x = x1 + w + d; + points[0].y = y1 - 1 + style->borderWidth.top - w_t; + points[1].y = y2 + 1 - style->borderWidth.bottom + w_b; + points[2].x = points[3].x = points[0].x + w; + points[2].y = y2 + 1 - style->borderWidth.bottom; + points[3].y = y1 - 1 + style->borderWidth.top; + view->drawPolygon (style->borderColor.left, shading, filled, convex, + points, 4); break; } } @@ -703,7 +724,9 @@ static void drawBorderRight(View *view, Style *style, int x1, int y1, int x2, int y2) { - int points[4][2], d, w; + int d, w; + Point points[4]; + const bool filled = true, convex = true; bool ridge = false, inset = false, dotted = false; Color::Shading shading = Color::SHADING_NORMAL; @@ -731,13 +754,14 @@ static void drawBorderRight(View *view, Style *style, if (style->borderWidth.right == 1) { /* 1 pixel line */ view->drawLine(style->borderColor.right, shading, x1, y1, x2, y2); } else { - points[0][0] = points[1][0] = x1 + 1; - points[0][1] = y1 - 1; - points[1][1] = y2 + 1; - points[2][0] = points[3][0] = points[0][0]-style->borderWidth.right; - points[2][1] = points[1][1] - style->borderWidth.bottom; - points[3][1] = points[0][1] + style->borderWidth.top; - view->drawPolygon (style->borderColor.right, shading, true,points,4); + points[0].x = points[1].x = x1 + 1; + points[0].y = y1 - 1; + points[1].y = y2 + 1; + points[2].x = points[3].x = points[0].x-style->borderWidth.right; + points[2].y = points[1].y - style->borderWidth.bottom; + points[3].y = points[0].y + style->borderWidth.top; + view->drawPolygon (style->borderColor.right, shading, filled, convex, + points,4); } break; case BORDER_RIDGE: @@ -745,22 +769,24 @@ static void drawBorderRight(View *view, Style *style, case BORDER_GROOVE: w = style->borderWidth.right; d = w & 1; - points[0][0] = points[1][0] = x1 + 1; - points[0][1] = y1; - points[1][1] = y2; - points[2][0] = points[3][0] = points[0][0] - w / 2 - d; - points[2][1] = y2 - style->borderWidth.bottom / 2; - points[3][1] = points[0][1] + style->borderWidth.top / 2; + points[0].x = points[1].x = x1 + 1; + points[0].y = y1; + points[1].y = y2; + points[2].x = points[3].x = points[0].x - w / 2 - d; + points[2].y = y2 - style->borderWidth.bottom / 2; + points[3].y = points[0].y + style->borderWidth.top / 2; shading = (ridge) ? Color::SHADING_DARK : Color::SHADING_LIGHT; - view->drawPolygon (style->borderColor.right, shading, true, points, 4); - points[0][0] = points[1][0] = x1 + 1 - w / 2 - d; - points[0][1] = y1 + style->borderWidth.top / 2; - points[1][1] = y2 - style->borderWidth.bottom / 2; - points[2][0] = points[3][0] = x1 + 1 - w; - points[2][1] = y2 - style->borderWidth.bottom; - points[3][1] = y1 + style->borderWidth.top; + view->drawPolygon (style->borderColor.right, shading, filled, convex, + points, 4); + points[0].x = points[1].x = x1 + 1 - w / 2 - d; + points[0].y = y1 + style->borderWidth.top / 2; + points[1].y = y2 - style->borderWidth.bottom / 2; + points[2].x = points[3].x = x1 + 1 - w; + points[2].y = y2 - style->borderWidth.bottom; + points[3].y = y1 + style->borderWidth.top; shading = (ridge) ? Color::SHADING_LIGHT: Color::SHADING_DARK; - view->drawPolygon (style->borderColor.right, shading, true, points, 4); + view->drawPolygon (style->borderColor.right, shading, filled, convex, + points, 4); break; case BORDER_DOUBLE: w = (int) rint(style->borderWidth.right / 3.0); @@ -771,20 +797,22 @@ static void drawBorderRight(View *view, Style *style, view->drawLine(style->borderColor.right, shading, x1, y1, x2, y2); break; } - points[0][0] = points[1][0] = x1 + 1; - points[0][1] = y1 - 1; - points[1][1] = y2 + 1; - points[2][0] = points[3][0] = points[0][0] - w; - points[2][1] = points[1][1] - w_b; - points[3][1] = points[0][1] + w_t; - view->drawPolygon (style->borderColor.right, shading, true, points, 4); - points[0][0] = points[1][0] = x1 + 1 - w - d; - points[0][1] = y1 - 1 + style->borderWidth.top - w_t; - points[1][1] = y2 + 1 - style->borderWidth.bottom + w_b; - points[2][0] = points[3][0] = points[0][0] - w; - points[2][1] = y2 + 1 - style->borderWidth.bottom; - points[3][1] = y1 - 1 + style->borderWidth.top; - view->drawPolygon (style->borderColor.right, shading, true, points, 4); + points[0].x = points[1].x = x1 + 1; + points[0].y = y1 - 1; + points[1].y = y2 + 1; + points[2].x = points[3].x = points[0].x - w; + points[2].y = points[1].y - w_b; + points[3].y = points[0].y + w_t; + view->drawPolygon (style->borderColor.right, shading, filled, convex, + points, 4); + points[0].x = points[1].x = x1 + 1 - w - d; + points[0].y = y1 - 1 + style->borderWidth.top - w_t; + points[1].y = y2 + 1 - style->borderWidth.bottom + w_b; + points[2].x = points[3].x = points[0].x - w; + points[2].y = y2 + 1 - style->borderWidth.bottom; + points[3].y = y1 - 1 + style->borderWidth.top; + view->drawPolygon (style->borderColor.right, shading, filled, convex, + points, 4); break; } } @@ -799,8 +827,7 @@ void drawBorder (View *view, Rectangle *area, Style *style, bool inverse) { /** \todo a lot! */ - Color::Shading dark, light, normal; - int xb1, yb1, xb2, yb2, xp1, yp1, xp2, yp2; + int xb1, yb1, xb2, yb2; // top left and bottom right point of outer border boundary xb1 = x + style->margin.left; @@ -808,15 +835,17 @@ void drawBorder (View *view, Rectangle *area, xb2 = x + (width > 0 ? width - 1 : 0) - style->margin.right; yb2 = y + (height > 0 ? height - 1 : 0) - style->margin.bottom; - // top left and bottom right point of inner border boundary - xp1 = xb1 + style->borderWidth.left; - yp1 = yb1 + style->borderWidth.top; - xp2 = xb2 - style->borderWidth.right; - yp2 = yb2 - style->borderWidth.bottom; - - light = inverse ? Color::SHADING_DARK : Color::SHADING_LIGHT; - dark = inverse ? Color::SHADING_LIGHT : Color::SHADING_DARK; - normal = inverse ? Color::SHADING_INVERSE : Color::SHADING_NORMAL; + /* + // top left and bottom right point of inner border boundary + xp1 = xb1 + style->borderWidth.left; + yp1 = yb1 + style->borderWidth.top; + xp2 = xb2 - style->borderWidth.right; + yp2 = yb2 - style->borderWidth.bottom; + + light = inverse ? Color::SHADING_DARK : Color::SHADING_LIGHT; + dark = inverse ? Color::SHADING_LIGHT : Color::SHADING_DARK; + normal = inverse ? Color::SHADING_INVERSE : Color::SHADING_NORMAL; + */ drawBorderRight(view, style, xb2, yb1, xb2, yb2); drawBorderLeft(view, style, xb1, yb1, xb1, yb2); diff --git a/dw/table.cc b/dw/table.cc index 6708b3f0..8a46ce7c 100644 --- a/dw/table.cc +++ b/dw/table.cc @@ -320,11 +320,19 @@ void Table::addCell (Widget *widget, int colspan, int rowspan) for (int col = 0; col < colspanEff; col++) for (int row = 0; row < rowspan; row++) if (!(col == 0 && row == 0)) { + int i = (curRow + row) * numCols + curCol + col; + + child = children->get(i); + if (child) { + MSG("Overlapping spans in table.\n"); + assert(child->type == Child::SPAN_SPACE); + delete child; + } child = new Child (); child->type = Child::SPAN_SPACE; child->spanSpace.startCol = curCol; child->spanSpace.startRow = curRow; - children->set ((curRow + row) * numCols + curCol + col, child); + children->set (i, child); } // Set the "root" cell. diff --git a/dw/textblock.cc b/dw/textblock.cc index fffbac2f..6ded2413 100644 --- a/dw/textblock.cc +++ b/dw/textblock.cc @@ -26,6 +26,15 @@ #include <math.h> // remove again #include <limits.h> +/* + * Local variables + */ + /* The tooltip under mouse pointer in current textblock. No ref. hold. + * (having one per view looks not worth the extra clutter). */ +static dw::core::style::Tooltip *hoverTooltip = NULL; + + + using namespace lout; namespace dw { @@ -81,8 +90,6 @@ Textblock::Textblock (bool limitTextWidth) availAscent = 100; availDescent = 0; - hoverTooltip = NULL; - this->limitTextWidth = limitTextWidth; for (int layer = 0; layer < core::HIGHLIGHT_NUM_LAYERS; layer++) { @@ -96,7 +103,10 @@ Textblock::Textblock (bool limitTextWidth) Textblock::~Textblock () { - //_MSG ("Textblock::~Textblock\n"); + _MSG("Textblock::~Textblock\n"); + + /* make sure not to call a free'd tooltip (very fast overkill) */ + hoverTooltip = NULL; for (int i = 0; i < words->size(); i++) { Word *word = words->getRef (i); @@ -372,13 +382,13 @@ void Textblock::sizeAllocateImpl (core::Allocation *allocation) * http://www.dillo.org/test/img/ */ childAllocation.y = lineYOffsetCanvasAllocation (line, allocation) - + (line->boxAscent - word->size.ascent); - // - word->content.widget->getStyle()->margin.top; + + (line->boxAscent - word->size.ascent) + - word->content.widget->getStyle()->margin.top; childAllocation.width = word->size.width; - childAllocation.ascent = word->size.ascent; - // + word->content.widget->getStyle()->margin.top; - childAllocation.descent = word->size.descent; - // + word->content.widget->getStyle()->margin.bottom; + childAllocation.ascent = word->size.ascent + + word->content.widget->getStyle()->margin.top; + childAllocation.descent = word->size.descent + + word->content.widget->getStyle()->margin.bottom; oldChildAllocation = word->content.widget->getAllocation(); @@ -609,6 +619,11 @@ bool Textblock::buttonReleaseImpl (core::EventButton *event) return sendSelectionEvent (core::SelectionState::BUTTON_RELEASE, event); } +/* + * Handle motion inside the widget + * (special care is necessary when switching from another widget, + * because hoverLink and hoverTooltip are meaningless then). + */ bool Textblock::motionNotifyImpl (core::EventMotion *event) { if (event->state & core::BUTTON1_MASK) @@ -630,6 +645,7 @@ bool Textblock::motionNotifyImpl (core::EventMotion *event) hoverLink = style->x_link; hoverTooltip = style->x_tooltip; } + // Show/hide tooltip if (tooltipOld != hoverTooltip) { if (tooltipOld) @@ -639,21 +655,32 @@ bool Textblock::motionNotifyImpl (core::EventMotion *event) } else if (hoverTooltip) hoverTooltip->onMotion (); - if (hoverLink != linkOld) + _MSG("MN tb=%p tooltipOld=%p hoverTooltip=%p\n", + this, tooltipOld, hoverTooltip); + if (hoverLink != linkOld) { + /* LinkEnter with hoverLink == -1 is the same as LinkLeave */ return layout->emitLinkEnter (this, hoverLink, -1, -1, -1); - else + } else { return hoverLink != -1; + } } } void Textblock::enterNotifyImpl (core::EventCrossing *event) { + _MSG(" tb=%p, ENTER NotifyImpl hoverTooltip=%p\n", this, hoverTooltip); + /* reset hoverLink so linkEnter is detected */ + hoverLink = -2; } void Textblock::leaveNotifyImpl (core::EventCrossing *event) { - hoverLink = -1; - (void) layout->emitLinkEnter (this, hoverLink, -1, -1, -1); + _MSG(" tb=%p, LEAVE NotifyImpl: hoverTooltip=%p\n", this, hoverTooltip); + + /* leaving the viewport can't be handled by motionNotifyImpl() */ + if (hoverLink >= 0) + layout->emitLinkEnter (this, -1, -1, -1, -1); + if (hoverTooltip) { hoverTooltip->onLeave(); hoverTooltip = NULL; @@ -671,10 +698,9 @@ bool Textblock::sendSelectionEvent (core::SelectionState::EventType eventType, int nextWordStartX, wordStartX, wordX, nextWordX, yFirst, yLast; int charPos = 0, link = -1, prevPos, wordIndex, lineIndex; Word *word; - bool found, r, withinContent = true; + bool found, r; if (words->size () == 0) { - withinContent = false; wordIndex = -1; } else { lastLine = lines->getRef (lines->size () - 1); @@ -683,12 +709,10 @@ bool Textblock::sendSelectionEvent (core::SelectionState::EventType eventType, lastLine->boxDescent; if (event->yCanvas < yFirst) { // Above the first line: take the first word. - withinContent = false; wordIndex = 0; charPos = 0; } else if (event->yCanvas >= yLast) { // Below the last line: take the last word. - withinContent = false; wordIndex = words->size () - 1; word = words->getRef (wordIndex); charPos = word->content.type == core::Content::TEXT ? @@ -701,13 +725,11 @@ bool Textblock::sendSelectionEvent (core::SelectionState::EventType eventType, if (event->yWidget > (lineYOffsetWidget (line) + line->boxAscent + line->boxDescent)) { // Choose this break. - withinContent = false; wordIndex = line->lastWord; charPos = 0; } else if (event->xWidget < lineXOffsetWidget (line)) { // Left of the first word in the line. wordIndex = line->firstWord; - withinContent = false; charPos = 0; } else { nextWordStartX = lineXOffsetWidget (line); @@ -761,7 +783,6 @@ bool Textblock::sendSelectionEvent (core::SelectionState::EventType eventType, if (!found) { // No word found in this line (i.e. we are on the right side), // take the last of this line. - withinContent = false; wordIndex = line->lastWord; if (wordIndex >= words->size ()) wordIndex--; @@ -775,8 +796,7 @@ bool Textblock::sendSelectionEvent (core::SelectionState::EventType eventType, } it = new TextblockIterator (this, core::Content::SELECTION_CONTENT, wordIndex); - r = selectionHandleEvent (eventType, it, charPos, link, event, - withinContent); + r = selectionHandleEvent (eventType, it, charPos, link, event); it->unref (); return r; } @@ -1058,29 +1078,29 @@ void Textblock::wordWrap(int wordIndex) // lastLine->boxDescent); if (word->content.type == core::Content::WIDGET) { + int collapseMarginTop = 0; + lastLine->marginDescent = misc::max (lastLine->marginDescent, word->size.descent + word->content.widget->getStyle()->margin.bottom); - //DBG_OBJ_ARRSET_NUM (page, "lines.%d.descent", page->num_lines - 1, - // lastLine->descent); + if (lines->size () == 1 && + word->content.widget->blockLevel () && + getStyle ()->borderWidth.top == 0 && + getStyle ()->padding.top == 0) { + // collapse top margin of parent element with top margin of first child + // see: http://www.w3.org/TR/CSS21/box.html#collapsing-margins + collapseMarginTop = getStyle ()->margin.top; + } - /* If the widget is not in the first line of the paragraph, its top - * margin may make the line higher. - */ - if (lines->size () > 1) { - /* Here, we know already what the break and the bottom margin - * contributed to the space before this line. - */ - lastLine->boxAscent = + lastLine->boxAscent = misc::max (lastLine->boxAscent, + word->size.ascent, word->size.ascent - + word->content.widget->getStyle()->margin.top); + + word->content.widget->getStyle()->margin.top + - collapseMarginTop); - //DBG_OBJ_ARRSET_NUM (page, "lines.%d.ascent", page->num_lines - 1, - // lastLine->boxAscent); - } } else { lastLine->marginDescent = misc::max (lastLine->marginDescent, lastLine->boxDescent); @@ -1197,11 +1217,7 @@ void Textblock::calcWidgetSize (core::Widget *widget, core::Requisition *size) widget->setAscent (availAscent); widget->setDescent (availDescent); widget->sizeRequest (size); -// size->ascent -= wstyle->margin.top; -// size->descent -= wstyle->margin.bottom; } else { - /* TODO: Use margin.{top|bottom} here, like above. - * (No harm for the next future.) */ if (wstyle->width == core::style::LENGTH_AUTO || wstyle->height == core::style::LENGTH_AUTO) widget->sizeRequest (&requisition); @@ -1232,6 +1248,10 @@ void Textblock::calcWidgetSize (core::Widget *widget, core::Requisition *size) size->descent = (int) (len * availDescent); } } + + /* ascent and descent in words do not contain margins. */ + size->ascent -= wstyle->margin.top; + size->descent -= wstyle->margin.bottom; } /** @@ -1499,11 +1519,6 @@ void Textblock::drawLine (Line *line, core::View *view, core::Rectangle *area) word->content.type == core::Content::WIDGET) { if (word->size.width > 0) { - if (word->style->hasBackground ()) { - drawBox (view, word->style, area, xWidget, - yWidgetBase - line->boxAscent, word->size.width, - line->boxAscent + line->boxDescent, false); - } if (word->content.type == core::Content::WIDGET) { core::Widget *child = word->content.widget; core::Rectangle childArea; @@ -1511,6 +1526,11 @@ void Textblock::drawLine (Line *line, core::View *view, core::Rectangle *area) if (child->intersects (area, &childArea)) child->draw (view, &childArea); } else { + if (word->style->hasBackground ()) { + drawBox (view, word->style, area, xWidget, + yWidgetBase - line->boxAscent, word->size.width, + line->boxAscent + line->boxDescent, false); + } drawText(wordIndex, view, area, xWidget, yWidgetBase); } } diff --git a/dw/textblock.hh b/dw/textblock.hh index baa5e29a..ea7795b8 100644 --- a/dw/textblock.hh +++ b/dw/textblock.hh @@ -315,9 +315,7 @@ protected: struct {int index, nChar;} hlStart[core::HIGHLIGHT_NUM_LAYERS], hlEnd[core::HIGHLIGHT_NUM_LAYERS]; - int hoverLink; /* The link under the button. */ - core::style::Tooltip *hoverTooltip; /* The tooltip under the button. No ref - * hold. */ + int hoverLink; /* The link under the mouse pointer */ void queueDrawRange (int index1, int index2); diff --git a/dw/types.cc b/dw/types.cc index 4d94f494..074cb352 100644 --- a/dw/types.cc +++ b/dw/types.cc @@ -140,16 +140,15 @@ void Polygon::draw (core::View *view, core::style::Style *style, int x, int y) { if (points->size()) { int i; - const bool filled = false; - int (*pointArray)[2] = - (int (*)[2]) malloc(points->size() * sizeof(*pointArray)); + const bool filled = false, convex = false; + Point *pointArray = (Point *)malloc(points->size()*sizeof(struct Point)); for (i = 0; i < points->size(); i++) { - pointArray[i][0] = x + points->getRef(i)->x; - pointArray[i][1] = y + points->getRef(i)->y; + pointArray[i].x = x + points->getRef(i)->x; + pointArray[i].y = y + points->getRef(i)->y; } view->drawPolygon(style->color, core::style::Color::SHADING_NORMAL, - filled, pointArray, i); + filled, convex, pointArray, i); free(pointArray); } } diff --git a/dw/types.hh b/dw/types.hh index 420a500f..b5204331 100644 --- a/dw/types.hh +++ b/dw/types.hh @@ -32,7 +32,8 @@ enum VPosition VPOS_NO_CHANGE }; -enum ScrollCommand {SCREEN_UP_CMD, SCREEN_DOWN_CMD, LINE_UP_CMD, LINE_DOWN_CMD, +enum ScrollCommand {SCREEN_UP_CMD, SCREEN_DOWN_CMD, SCREEN_LEFT_CMD, + SCREEN_RIGHT_CMD, LINE_UP_CMD, LINE_DOWN_CMD, LEFT_CMD, RIGHT_CMD, TOP_CMD, BOTTOM_CMD}; /* @@ -266,9 +266,9 @@ void ComplexButtonResource::LayoutReceiver::canvasSizeChanged (int width, int descent) { /** - * \todo The argument to queueResize is not always true. (But this works.) + * \todo Verify that this is correct. */ - resource->queueResize (true); + resource->queueResize (resource->childWidget->extremesChanged ()); } ComplexButtonResource::ComplexButtonResource () @@ -421,12 +421,10 @@ class SelectionResource: public Resource { public: virtual void addItem (const char *str, bool enabled, bool selected) = 0; - virtual void pushGroup (const char *name, bool enabled) = 0; virtual void popGroup () = 0; virtual int getNumberOfItems () = 0; - virtual const char *getItem (int index) = 0; virtual bool isSelected (int index) = 0; }; @@ -92,12 +92,6 @@ public: * This will normally imply a resize of the UI widget. Width and height are * the dimensions of the new size, \em including the scrollbar thicknesses. * - * \bug The rest of this comment needs to be updated. - * - * markerWidthDiff and markerHeightDiff are the respective dimensions of - * the viewport markers (see dw::core::getMarkerWidthDiff and - * dw::core::getMarkerHeightDiff), if they are 0, the respective - * marker should not be shown at all. */ virtual void setViewportSize (int width, int height, int hScrollbarThickness, @@ -179,12 +173,16 @@ public: int angle1, int angle2) = 0; virtual void drawPolygon (style::Color *color, style::Color::Shading shading, - bool filled, int points[][2], int npoints) = 0; + bool filled, bool convex, Point *points, + int npoints) = 0; virtual void drawText (style::Font *font, style::Color *color, style::Color::Shading shading, int x, int y, const char *text, int len) = 0; - + virtual void drawSimpleWrappedText (style::Font *font, style::Color *color, + style::Color::Shading shading, + int x, int y, int w, int h, + const char *text) = 0; virtual void drawImage (Imgbuf *imgbuf, int xRoot, int yRoot, int x, int y, int width, int height) = 0; diff --git a/dw/widget.hh b/dw/widget.hh index 3034b982..e18344c7 100644 --- a/dw/widget.hh +++ b/dw/widget.hh @@ -206,25 +206,21 @@ protected: inline bool selectionButtonPress (Iterator *it, int charPos, int linkNo, EventButton *event, bool withinContent) - { return layout->selectionState.buttonPress (it, charPos, linkNo, event, - withinContent); } + { return layout->selectionState.buttonPress (it, charPos, linkNo, event); } inline bool selectionButtonRelease (Iterator *it, int charPos, int linkNo, EventButton *event, bool withinContent) - { return layout->selectionState.buttonRelease (it, charPos, linkNo, event, - withinContent); } + { return layout->selectionState.buttonRelease (it, charPos, linkNo, event);} inline bool selectionButtonMotion (Iterator *it, int charPos, int linkNo, EventMotion *event, bool withinContent) - { return layout->selectionState.buttonMotion (it, charPos, linkNo, event, - withinContent); } + { return layout->selectionState.buttonMotion (it, charPos, linkNo, event); } inline bool selectionHandleEvent (SelectionState::EventType eventType, Iterator *it, int charPos, int linkNo, - MousePositionEvent *event, - bool withinContent) + MousePositionEvent *event) { return layout->selectionState.handleEvent (eventType, it, charPos, linkNo, - event, withinContent); } + event); } private: void *deleteCallbackData; |