Added new flags for label alignment: FL_LEFT_TOP, FL_RIGHT_TOP, FL_LEFT_BOTTOM, and FL_RIGHT_BOTTOM align outside labels first to the side, then to the top or botton, filling a gap in possible alignment. Also FL_ALIGN_TEXT_NEXT_TO_IMAGE and FL_ALIGN_IMAGE_NEXT_TO_TEXT which do just that, and finally FL_ALIGN_IMAGE_BACKDROP which renders the image in the background and draws the label on top.

git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@7469 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
Matthias Melcher 2010-04-07 23:17:33 +00:00
parent 0fe65e94c9
commit f899c3897d
7 changed files with 139 additions and 29 deletions

View File

@ -1,5 +1,6 @@
CHANGES IN FLTK 1.3.0 CHANGES IN FLTK 1.3.0
- Added new label and image alignments (STR #2269)
- Added documentation for event delivery (STR #1983) - Added documentation for event delivery (STR #1983)
- Fixed menu and tooltip window animation bug under X11 (compiz) - Fixed menu and tooltip window animation bug under X11 (compiz)
by setting an appropriate window type (STR #2082) by setting an appropriate window type (STR #2082)

View File

@ -618,6 +618,27 @@ extern Fl_Labeltype FL_EXPORT fl_define_FL_EMBOSSED_LABEL();
* inside the widget. * inside the widget.
* *
* Flags can be or'd to achieve a combination of alignments. * 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. * \see #FL_ALIGN_CENTER, etc.
*/ */
typedef unsigned Fl_Align; 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; const Fl_Align FL_ALIGN_CLIP = (Fl_Align)64;
/** Wrap text that does not fit the width of the widget. */ /** Wrap text that does not fit the width of the widget. */
const Fl_Align FL_ALIGN_WRAP = (Fl_Align)128; 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_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_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_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_BOTTOM_RIGHT = FL_ALIGN_BOTTOM | FL_ALIGN_RIGHT;
const Fl_Align FL_ALIGN_LEFT_TOP = FL_ALIGN_TOP_LEFT; const Fl_Align FL_ALIGN_LEFT_TOP = 0x0007; // magic value
const Fl_Align FL_ALIGN_RIGHT_TOP = FL_ALIGN_TOP_RIGHT; const Fl_Align FL_ALIGN_RIGHT_TOP = 0x000b; // magic value
const Fl_Align FL_ALIGN_LEFT_BOTTOM = FL_ALIGN_BOTTOM_LEFT; const Fl_Align FL_ALIGN_LEFT_BOTTOM = 0x000d; // magic value
const Fl_Align FL_ALIGN_RIGHT_BOTTOM = FL_ALIGN_BOTTOM_RIGHT; const Fl_Align FL_ALIGN_RIGHT_BOTTOM = 0x000e; // magic value
const Fl_Align FL_ALIGN_NOWRAP = (Fl_Align)0; // for back compatability const Fl_Align FL_ALIGN_NOWRAP = (Fl_Align)0; // for back compatability
/*@}*/ /*@}*/
/** \name Font Numbers */ /** \name Font Numbers */
/*@{*/ /*@{*/
/** A font number is an index into the internal font table. /** A font number is an index into the internal font table.

View File

@ -170,6 +170,7 @@ protected:
void draw_box() const; void draw_box() const;
void draw_box(Fl_Boxtype t, Fl_Color c) 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_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 */ /** draws a focus rectangle around the widget */
void draw_focus() {draw_focus(box(),x(),y(),w(),h());} 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; void draw_focus(Fl_Boxtype t, int x,int y,int w,int h) const;
@ -497,6 +498,7 @@ public:
\return the current image \return the current image
*/ */
Fl_Image* image() {return label_.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. /** Sets the image to use as part of the widget label.
This image is used when drawing the widget in the active state. 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 \return the current image for the deactivated widget
*/ */
Fl_Image* deimage() {return label_.deimage;} 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. /** Sets the image to use as part of the widget label.
This image is used when drawing the widget in the inactive state. This image is used when drawing the widget in the inactive state.

View File

@ -745,7 +745,23 @@ void Fl_Group::draw_outside_label(const Fl_Widget& widget) const {
int Y = widget.y(); int Y = widget.y();
int W = widget.w(); int W = widget.w();
int H = widget.h(); 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); a ^= (FL_ALIGN_BOTTOM|FL_ALIGN_TOP);
Y = y(); Y = y();
H = widget.y()-Y; H = widget.y()-Y;

View File

@ -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 //extern Fl_Widget *fl_boxcheat; // hack set by Fl_Window.cxx
/** Draws the widget box according its box style */ /** Draws the widget box according its box style */
void Fl_Widget::draw_box() const { void Fl_Widget::draw_box() const {
int t = box_; if (box_) draw_box((Fl_Boxtype)box_, x_, y_, w_, h_, color_);
if (!t) return; draw_backdrop();
// if (this == fl_boxcheat) { }
// fl_boxcheat = 0; /** If FL_ALIGN_IMAGE_BACKDROP is set, the image or deimage will be drawn */
// if (t == FL_FLAT_BOX) return; void Fl_Widget::draw_backdrop() const {
// t += 2; // convert box to frame if (align() & FL_ALIGN_IMAGE_BACKDROP) {
// } const Fl_Image *img = image();
draw_box((Fl_Boxtype)t, x_, y_, w_, h_, color_); // 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. */ /** 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 { void Fl_Widget::draw_box(Fl_Boxtype t, Fl_Color c) const {

View File

@ -186,7 +186,8 @@ void fl_draw(
int x, int y, int w, int h, // bounding box int x, int y, int w, int h, // bounding box
Fl_Align align, Fl_Align align,
void (*callthis)(const char*,int,int,int), void (*callthis)(const char*,int,int,int),
Fl_Image* img, int draw_symbols) { Fl_Image* img, int draw_symbols)
{
const char* p; const char* p;
const char* e; const char* e;
char buf[MAXBUF]; char buf[MAXBUF];
@ -198,6 +199,9 @@ void fl_draw(
int lines; int lines;
double width; 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'; symbol[0][0] = '\0';
symwidth[0] = 0; symwidth[0] = 0;
@ -223,14 +227,18 @@ void fl_draw(
symtotal = symwidth[0] + symwidth[1]; symtotal = symwidth[0] + symwidth[1];
int strw = 0;
int strh;
if (str) { 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, e = fl_expand_text(p, buf, MAXBUF, w - symtotal, buflen, width,
align&FL_ALIGN_WRAP, draw_symbols); align&FL_ALIGN_WRAP, draw_symbols);
lines++; if (strw<width) strw = width;
if (!*e || (*e == '@' && e[1] != '@' && draw_symbols)) break; lines++;
p = e; if (!*e || (*e == '@' && e[1] != '@' && draw_symbols)) break;
} p = e;
}
} else lines = 0; } else lines = 0;
if ((symwidth[0] || symwidth[1]) && lines) { if ((symwidth[0] || symwidth[1]) && lines) {
@ -239,12 +247,15 @@ void fl_draw(
} }
symtotal = symwidth[0] + symwidth[1]; symtotal = symwidth[0] + symwidth[1];
strh = lines * fl_height();
// figure out vertical position of the first line: // figure out vertical position of the first line:
int xpos; int xpos;
int ypos; int ypos;
int height = fl_height(); int height = fl_height();
int imgh = img ? img->h() : 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; symoffset = 0;
@ -253,7 +264,7 @@ void fl_draw(
else ypos = y+(h-lines*height-imgh)/2+height; else ypos = y+(h-lines*height-imgh)/2+height;
// draw the image unless the "text over image" alignment flag is set... // 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 (img->w() > symoffset) symoffset = img->w();
if (align & FL_ALIGN_LEFT) xpos = x + symwidth[0]; if (align & FL_ALIGN_LEFT) xpos = x + symwidth[0];
@ -264,6 +275,26 @@ void fl_draw(
ypos += img->h(); 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: // now draw all the lines:
if (str) { if (str) {
int desc = fl_descent(); int desc = fl_descent();
@ -274,9 +305,9 @@ void fl_draw(
if (width > symoffset) symoffset = (int)(width + 0.5); if (width > symoffset) symoffset = (int)(width + 0.5);
if (align & FL_ALIGN_LEFT) xpos = x + 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]; else if (align & FL_ALIGN_RIGHT) xpos = x + w - (int)(width + .5) - symwidth[1] - imgw[1];
else xpos = x + (w - (int)(width + .5) - symtotal) / 2 + symwidth[0]; else xpos = x + (w - (int)(width + .5) - symtotal - imgw[0] - imgw[1]) / 2 + symwidth[0] + imgw[0];
callthis(buf,buflen,xpos,ypos-desc); 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... // 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 (img->w() > symoffset) symoffset = img->w();
if (align & FL_ALIGN_LEFT) xpos = x + symwidth[0]; if (align & FL_ALIGN_LEFT) xpos = x + symwidth[0];

View File

@ -32,14 +32,19 @@
#include <FL/Fl_Toggle_Button.H> #include <FL/Fl_Toggle_Button.H>
#include <FL/Fl_Input.H> #include <FL/Fl_Input.H>
#include <FL/Fl_Choice.H> #include <FL/Fl_Choice.H>
#include <FL/Fl_Pixmap.H>
#include <FL/fl_draw.H> #include <FL/fl_draw.H>
#include "pixmaps/blast.xpm"
Fl_Toggle_Button *imageb, *imageovertextb, *imagenexttotextb, *imagebackdropb;
Fl_Toggle_Button *leftb,*rightb,*topb,*bottomb,*insideb,*clipb,*wrapb; Fl_Toggle_Button *leftb,*rightb,*topb,*bottomb,*insideb,*clipb,*wrapb;
Fl_Box *text; Fl_Box *text;
Fl_Input *input; Fl_Input *input;
Fl_Hor_Value_Slider *fonts; Fl_Hor_Value_Slider *fonts;
Fl_Hor_Value_Slider *sizes; Fl_Hor_Value_Slider *sizes;
Fl_Double_Window *window; Fl_Double_Window *window;
Fl_Pixmap *img;
void button_cb(Fl_Widget *,void *) { void button_cb(Fl_Widget *,void *) {
int i = 0; int i = 0;
@ -50,10 +55,21 @@ void button_cb(Fl_Widget *,void *) {
if (insideb->value()) i |= FL_ALIGN_INSIDE; if (insideb->value()) i |= FL_ALIGN_INSIDE;
if (clipb->value()) i |= FL_ALIGN_CLIP; if (clipb->value()) i |= FL_ALIGN_CLIP;
if (wrapb->value()) i |= FL_ALIGN_WRAP; 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); text->align(i);
window->redraw(); 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 *) { void font_cb(Fl_Widget *,void *) {
text->labelfont(int(fonts->value())); text->labelfont(int(fonts->value()));
window->redraw(); window->redraw();
@ -107,6 +123,8 @@ Fl_Menu_Item choices[] = {
{0}}; {0}};
int main(int argc, char **argv) { int main(int argc, char **argv) {
img = new Fl_Pixmap(blast_xpm);
window = new Fl_Double_Window(400,400); window = new Fl_Double_Window(400,400);
input = new Fl_Input(50,375,350,25); input = new Fl_Input(50,375,350,25);
@ -128,7 +146,15 @@ int main(int argc, char **argv) {
fonts->value(0); fonts->value(0);
fonts->callback(font_cb); 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 = new Fl_Toggle_Button(50,300,50,25,"left");
leftb->callback(button_cb); leftb->callback(button_cb);
rightb = new Fl_Toggle_Button(100,300,50,25,"right"); rightb = new Fl_Toggle_Button(100,300,50,25,"right");
@ -146,7 +172,7 @@ int main(int argc, char **argv) {
g->resizable(insideb); g->resizable(insideb);
g->end(); 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); c->menu(choices);
text= new Fl_Box(FL_FRAME_BOX,100,75,200,100,input->value()); text= new Fl_Box(FL_FRAME_BOX,100,75,200,100,input->value());