diff --git a/CHANGES b/CHANGES index 9eafd32bc..cc402681f 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,6 @@ CHANGES IN FLTK 1.3.0 + - Added new label and image alignments (STR #2269) - Added documentation for event delivery (STR #1983) - Fixed menu and tooltip window animation bug under X11 (compiz) by setting an appropriate window type (STR #2082) diff --git a/FL/Enumerations.H b/FL/Enumerations.H index e3e53eb36..b2e5aa367 100644 --- a/FL/Enumerations.H +++ b/FL/Enumerations.H @@ -618,6 +618,27 @@ extern Fl_Labeltype FL_EXPORT fl_define_FL_EMBOSSED_LABEL(); * inside the widget. * * Flags can be or'd to achieve a combination of alignments. + * + * Outside alignments: + * \code + * TOP_LEFT TOP TOP_RIGHT + * LEFT_TOP+---------------------------------+RIGHT_TOP + * | | + * LEFT| |RIGHT + * | | + * LEFT_BOTTOM+---------------------------------+RIGHT_BOTTOM + * BOTTOM_RIGHT BOTTOM BOTTOM_LEFT + * + * Inside alignments: + * \code + * +---------------------------------+ + * |TOP_LEFT TOP TOP_RIGHT| + * | | + * |LEFT RIGHT| + * | | + * |BOTTOM_RIGHT BOTTOM BOTTOM_LEFT| + * +---------------------------------+ + * \endcode * \see #FL_ALIGN_CENTER, etc. */ typedef unsigned Fl_Align; @@ -644,17 +665,24 @@ const Fl_Align FL_ALIGN_IMAGE_OVER_TEXT = (Fl_Align)0; const Fl_Align FL_ALIGN_CLIP = (Fl_Align)64; /** Wrap text that does not fit the width of the widget. */ const Fl_Align FL_ALIGN_WRAP = (Fl_Align)128; + /** If the label contains an image, draw the text to the left of the image. */ +const Fl_Align FL_ALIGN_TEXT_NEXT_TO_IMAGE = (Fl_Align)0x0100; + /** If the label contains an image, draw the text to the right of the image. */ +const Fl_Align FL_ALIGN_IMAGE_NEXT_TO_TEXT = (Fl_Align)0x0110; +/** If the label contains an image, draw the image or deimage in the backgroup. */ +const Fl_Align FL_ALIGN_IMAGE_BACKDROP = (Fl_Align)0x0200; const Fl_Align FL_ALIGN_TOP_LEFT = FL_ALIGN_TOP | FL_ALIGN_LEFT; const Fl_Align FL_ALIGN_TOP_RIGHT = FL_ALIGN_TOP | FL_ALIGN_RIGHT; const Fl_Align FL_ALIGN_BOTTOM_LEFT = FL_ALIGN_BOTTOM | FL_ALIGN_LEFT; const Fl_Align FL_ALIGN_BOTTOM_RIGHT = FL_ALIGN_BOTTOM | FL_ALIGN_RIGHT; -const Fl_Align FL_ALIGN_LEFT_TOP = FL_ALIGN_TOP_LEFT; -const Fl_Align FL_ALIGN_RIGHT_TOP = FL_ALIGN_TOP_RIGHT; -const Fl_Align FL_ALIGN_LEFT_BOTTOM = FL_ALIGN_BOTTOM_LEFT; -const Fl_Align FL_ALIGN_RIGHT_BOTTOM = FL_ALIGN_BOTTOM_RIGHT; +const Fl_Align FL_ALIGN_LEFT_TOP = 0x0007; // magic value +const Fl_Align FL_ALIGN_RIGHT_TOP = 0x000b; // magic value +const Fl_Align FL_ALIGN_LEFT_BOTTOM = 0x000d; // magic value +const Fl_Align FL_ALIGN_RIGHT_BOTTOM = 0x000e; // magic value const Fl_Align FL_ALIGN_NOWRAP = (Fl_Align)0; // for back compatability /*@}*/ + /** \name Font Numbers */ /*@{*/ /** A font number is an index into the internal font table. diff --git a/FL/Fl_Widget.H b/FL/Fl_Widget.H index a3a2d6ad6..3e61c7534 100644 --- a/FL/Fl_Widget.H +++ b/FL/Fl_Widget.H @@ -170,6 +170,7 @@ protected: void draw_box() const; void draw_box(Fl_Boxtype t, Fl_Color c) const; void draw_box(Fl_Boxtype t, int x,int y,int w,int h, Fl_Color c) const; + void draw_backdrop() const; /** draws a focus rectangle around the widget */ void draw_focus() {draw_focus(box(),x(),y(),w(),h());} void draw_focus(Fl_Boxtype t, int x,int y,int w,int h) const; @@ -497,6 +498,7 @@ public: \return the current image */ Fl_Image* image() {return label_.image;} + const Fl_Image* image() const {return label_.image;} /** Sets the image to use as part of the widget label. This image is used when drawing the widget in the active state. @@ -515,6 +517,7 @@ public: \return the current image for the deactivated widget */ Fl_Image* deimage() {return label_.deimage;} + const Fl_Image* deimage() const {return label_.deimage;} /** Sets the image to use as part of the widget label. This image is used when drawing the widget in the inactive state. diff --git a/src/Fl_Group.cxx b/src/Fl_Group.cxx index a5ca1739b..8f02fcf46 100644 --- a/src/Fl_Group.cxx +++ b/src/Fl_Group.cxx @@ -745,7 +745,23 @@ void Fl_Group::draw_outside_label(const Fl_Widget& widget) const { int Y = widget.y(); int W = widget.w(); int H = widget.h(); - if (a & FL_ALIGN_TOP) { + if ( (a & 0x0f) == FL_ALIGN_LEFT_TOP ) { + a = (a &~0x0f ) | FL_ALIGN_TOP_RIGHT; + X = x(); + W = widget.x()-X-3; + } else if ( (a & 0x0f) == FL_ALIGN_LEFT_BOTTOM ) { + a = (a &~0x0f ) | FL_ALIGN_BOTTOM_RIGHT; + X = x(); + W = widget.x()-X-3; + } else if ( (a & 0x0f) == FL_ALIGN_RIGHT_TOP ) { + a = (a &~0x0f ) | FL_ALIGN_TOP_LEFT; + X = X+W+3; + W = x()+this->w()-X; + } else if ( (a & 0x0f) == FL_ALIGN_RIGHT_BOTTOM ) { + a = (a &~0x0f ) | FL_ALIGN_BOTTOM_LEFT; + X = X+W+3; + W = x()+this->w()-X; + } else if (a & FL_ALIGN_TOP) { a ^= (FL_ALIGN_BOTTOM|FL_ALIGN_TOP); Y = y(); H = widget.y()-Y; diff --git a/src/fl_boxtype.cxx b/src/fl_boxtype.cxx index f4ae05941..c8a824e5c 100644 --- a/src/fl_boxtype.cxx +++ b/src/fl_boxtype.cxx @@ -399,14 +399,19 @@ void fl_draw_box(Fl_Boxtype t, int x, int y, int w, int h, Fl_Color c) { //extern Fl_Widget *fl_boxcheat; // hack set by Fl_Window.cxx /** Draws the widget box according its box style */ void Fl_Widget::draw_box() const { - int t = box_; - if (!t) return; -// if (this == fl_boxcheat) { -// fl_boxcheat = 0; -// if (t == FL_FLAT_BOX) return; -// t += 2; // convert box to frame -// } - draw_box((Fl_Boxtype)t, x_, y_, w_, h_, color_); + if (box_) draw_box((Fl_Boxtype)box_, x_, y_, w_, h_, color_); + draw_backdrop(); +} +/** If FL_ALIGN_IMAGE_BACKDROP is set, the image or deimage will be drawn */ +void Fl_Widget::draw_backdrop() const { + if (align() & FL_ALIGN_IMAGE_BACKDROP) { + const Fl_Image *img = image(); + // if there is no image, we will not draw the deimage either + if (img && deimage() && !active_r()) + img = deimage(); + if (img) + ((Fl_Image*)img)->draw(x_+(w_-img->w())/2, y_+(h_-img->h())/2); + } } /** Draws a box of type t, of color c at the widget's position and size. */ void Fl_Widget::draw_box(Fl_Boxtype t, Fl_Color c) const { diff --git a/src/fl_draw.cxx b/src/fl_draw.cxx index d435bf82b..27f50afad 100644 --- a/src/fl_draw.cxx +++ b/src/fl_draw.cxx @@ -186,7 +186,8 @@ void fl_draw( int x, int y, int w, int h, // bounding box Fl_Align align, void (*callthis)(const char*,int,int,int), - Fl_Image* img, int draw_symbols) { + Fl_Image* img, int draw_symbols) +{ const char* p; const char* e; char buf[MAXBUF]; @@ -198,6 +199,9 @@ void fl_draw( int lines; double width; + // if the image is set as a backdrop, ignore it here + if (img && (align & FL_ALIGN_IMAGE_BACKDROP)) img = 0; + symbol[0][0] = '\0'; symwidth[0] = 0; @@ -222,29 +226,36 @@ void fl_draw( } symtotal = symwidth[0] + symwidth[1]; + + int strw = 0; + int strh; if (str) { - for (p = str, lines=0; p;) { + for (p = str, lines=0; p;) { e = fl_expand_text(p, buf, MAXBUF, w - symtotal, buflen, width, - align&FL_ALIGN_WRAP, draw_symbols); - lines++; - if (!*e || (*e == '@' && e[1] != '@' && draw_symbols)) break; - p = e; - } + align&FL_ALIGN_WRAP, draw_symbols); + if (strwh() : 0; + int imgvert = ((align&FL_ALIGN_TEXT_NEXT_TO_IMAGE)==0); + int imgh = img && imgvert ? img->h() : 0; + int imgw[2] = {0, 0}; symoffset = 0; @@ -253,7 +264,7 @@ void fl_draw( else ypos = y+(h-lines*height-imgh)/2+height; // draw the image unless the "text over image" alignment flag is set... - if (img && !(align & FL_ALIGN_TEXT_OVER_IMAGE)) { + if (img && imgvert && !(align & FL_ALIGN_TEXT_OVER_IMAGE)) { if (img->w() > symoffset) symoffset = img->w(); if (align & FL_ALIGN_LEFT) xpos = x + symwidth[0]; @@ -264,6 +275,26 @@ void fl_draw( ypos += img->h(); } + // draw the image to the side of the text + if (img && !imgvert /* && (align & !FL_ALIGN_TEXT_NEXT_TO_IMAGE)*/ ) { + if (align & FL_ALIGN_TEXT_OVER_IMAGE) { // image is right of text + imgw[1] = img->w(); + if (align & FL_ALIGN_LEFT) xpos = x + symwidth[0] + strw + 1; + else if (align & FL_ALIGN_RIGHT) xpos = x + w - symwidth[1] - imgw[1] + 1; + else xpos = x + (w - strw - symtotal - imgw[1]) / 2 + symwidth[0] + strw + 1; + } else { // image is to the left of the text + imgw[0] = img->w(); + if (align & FL_ALIGN_LEFT) xpos = x + symwidth[0] - 1; + else if (align & FL_ALIGN_RIGHT) xpos = x + w - symwidth[1] - strw - imgw[0] - 1; + else xpos = x + (w - strw - symtotal - imgw[0]) / 2 - 1; + } + int yimg = ypos - height; + if (align & FL_ALIGN_TOP) ; + else if (align & FL_ALIGN_BOTTOM) yimg += strh - img->h() - 1; + else yimg += (strh - img->h() - 1) / 2; + img->draw(xpos, yimg); + } + // now draw all the lines: if (str) { int desc = fl_descent(); @@ -274,9 +305,9 @@ void fl_draw( if (width > symoffset) symoffset = (int)(width + 0.5); - if (align & FL_ALIGN_LEFT) xpos = x + symwidth[0]; - else if (align & FL_ALIGN_RIGHT) xpos = x + w - (int)(width + .5) - symwidth[1]; - else xpos = x + (w - (int)(width + .5) - symtotal) / 2 + symwidth[0]; + if (align & FL_ALIGN_LEFT) xpos = x + symwidth[0] + imgw[0]; + else if (align & FL_ALIGN_RIGHT) xpos = x + w - (int)(width + .5) - symwidth[1] - imgw[1]; + else xpos = x + (w - (int)(width + .5) - symtotal - imgw[0] - imgw[1]) / 2 + symwidth[0] + imgw[0]; callthis(buf,buflen,xpos,ypos-desc); @@ -289,7 +320,7 @@ void fl_draw( } // draw the image if the "text over image" alignment flag is set... - if (img && (align & FL_ALIGN_TEXT_OVER_IMAGE)) { + if (img && imgvert && (align & FL_ALIGN_TEXT_OVER_IMAGE)) { if (img->w() > symoffset) symoffset = img->w(); if (align & FL_ALIGN_LEFT) xpos = x + symwidth[0]; diff --git a/test/label.cxx b/test/label.cxx index 35927552f..2d5fee5cb 100644 --- a/test/label.cxx +++ b/test/label.cxx @@ -32,14 +32,19 @@ #include #include #include +#include #include +#include "pixmaps/blast.xpm" + +Fl_Toggle_Button *imageb, *imageovertextb, *imagenexttotextb, *imagebackdropb; Fl_Toggle_Button *leftb,*rightb,*topb,*bottomb,*insideb,*clipb,*wrapb; Fl_Box *text; Fl_Input *input; Fl_Hor_Value_Slider *fonts; Fl_Hor_Value_Slider *sizes; Fl_Double_Window *window; +Fl_Pixmap *img; void button_cb(Fl_Widget *,void *) { int i = 0; @@ -50,10 +55,21 @@ void button_cb(Fl_Widget *,void *) { if (insideb->value()) i |= FL_ALIGN_INSIDE; if (clipb->value()) i |= FL_ALIGN_CLIP; if (wrapb->value()) i |= FL_ALIGN_WRAP; + if (imageovertextb->value()) i |= FL_ALIGN_TEXT_OVER_IMAGE; + if (imagenexttotextb->value()) i |= FL_ALIGN_TEXT_NEXT_TO_IMAGE; + if (imagebackdropb->value()) i |= FL_ALIGN_IMAGE_BACKDROP; text->align(i); window->redraw(); } +void image_cb(Fl_Widget *,void *) { + if (imageb->value()) + text->image(img); + else + text->image(0); + window->redraw(); +} + void font_cb(Fl_Widget *,void *) { text->labelfont(int(fonts->value())); window->redraw(); @@ -107,6 +123,8 @@ Fl_Menu_Item choices[] = { {0}}; int main(int argc, char **argv) { + img = new Fl_Pixmap(blast_xpm); + window = new Fl_Double_Window(400,400); input = new Fl_Input(50,375,350,25); @@ -128,7 +146,15 @@ int main(int argc, char **argv) { fonts->value(0); fonts->callback(font_cb); - Fl_Group *g = new Fl_Group(50,300,350,25); + Fl_Group *g = new Fl_Group(50,275,350,50); + imageb = new Fl_Toggle_Button(50,275,50,25,"image"); + imageb->callback(image_cb); + imageovertextb = new Fl_Toggle_Button(100,275,50,25,"I - T"); + imageovertextb->callback(button_cb); + imagenexttotextb = new Fl_Toggle_Button(150,275,50,25,"I | T"); + imagenexttotextb->callback(button_cb); + imagebackdropb = new Fl_Toggle_Button(200,275,50,25,"back"); + imagebackdropb->callback(button_cb); leftb = new Fl_Toggle_Button(50,300,50,25,"left"); leftb->callback(button_cb); rightb = new Fl_Toggle_Button(100,300,50,25,"right"); @@ -146,7 +172,7 @@ int main(int argc, char **argv) { g->resizable(insideb); g->end(); - Fl_Choice *c = new Fl_Choice(50,275,200,25); + Fl_Choice *c = new Fl_Choice(50,250,200,25); c->menu(choices); text= new Fl_Box(FL_FRAME_BOX,100,75,200,100,input->value());