move triangle drawing into FbDrawable

Make MenuItem triangles proportional
This commit is contained in:
simonb 2007-01-06 07:38:04 +00:00
parent 2e438fde2c
commit 1f7b12cc49
8 changed files with 118 additions and 91 deletions

View file

@ -1,5 +1,11 @@
(Format: Year/Month/Day)
Changes for 1.0rc3:
*07/01/06:
* Move triangle drawing into a generic function in FbDrawable (Simon)
Make submenu triangles in MenuItems proportional to the icon size
(alternate implementation of sf.net patch #1526813)
FbTk/... FbDrawable.hh/cc MenuItem.cc
ArrowButton.hh/cc WinButton.cc ToolFactory.cc
*07/01/05:
* When a client in an unfocused tab creates a transient window, set that
client to the active tab (Mark)

View file

@ -24,27 +24,27 @@
#include "ArrowButton.hh"
#include "ButtonTheme.hh"
ArrowButton::ArrowButton(ArrowButton::Type arrow_type,
ArrowButton::ArrowButton(FbTk::FbDrawable::TriangleType arrow_type,
const FbTk::FbWindow &parent,
int x, int y,
unsigned int width, unsigned int height):
FbTk::Button(parent, x, y, width, height),
m_arrow_type(arrow_type),
m_mouse_handler(0),
m_arrowscale(300) {
m_arrowscale(250) {
setEventMask(ExposureMask | ButtonPressMask | ButtonReleaseMask |
EnterWindowMask | LeaveWindowMask);
}
ArrowButton::ArrowButton(ArrowButton::Type arrow_type,
ArrowButton::ArrowButton(FbTk::FbDrawable::TriangleType arrow_type,
int screen_num,
int x, int y,
unsigned int width, unsigned int height):
FbTk::Button(screen_num, x, y, width, height),
m_arrow_type(arrow_type),
m_mouse_handler(0),
m_arrowscale(300) {
m_arrowscale(250) {
setEventMask(ExposureMask | ButtonPressMask | ButtonReleaseMask |
EnterWindowMask | LeaveWindowMask);
@ -84,46 +84,8 @@ void ArrowButton::leaveNotifyEvent(XCrossingEvent &ce) {
redraws the arrow button
*/
void ArrowButton::drawArrow() {
XPoint pts[3];
unsigned int w = width();
unsigned int h = height();
int arrowscale_n = m_arrowscale;
int arrowscale_d = 100;
unsigned int ax = arrowscale_d * w / arrowscale_n;
unsigned int ay = arrowscale_d * h / arrowscale_n;
// if these aren't an even number, left and right arrows end up different
if (( ax % 2 ) == 1) ax++;
if (( ay % 2 ) == 1) ay++;
switch (m_arrow_type) {
case LEFT:
// start at the tip
pts[0].x = (w / 2) - (ax / 2); pts[0].y = h / 2;
pts[1].x = ax; pts[1].y = -ay / 2;
pts[2].x = 0; pts[2].y = ay;
break;
case RIGHT:
pts[0].x = (w / 2) + (ax / 2); pts[0].y = h / 2;
pts[1].x = - ax; pts[1].y = ay / 2;
pts[2].x = 0; pts[2].y = - ay;
break;
case UP:
pts[0].x = (w / 2); pts[0].y = (h / 2) - (ay / 2);
pts[1].x = ax / 2; pts[1].y = ay;
pts[2].x = - ax; pts[2].y = 0;
break;
case DOWN:
pts[0].x = (w / 2); pts[0].y = (h / 2) + (ay / 2);
pts[1].x = ax / 2; pts[1].y = - ay;
pts[2].x = - ax; pts[2].y = 0;
break;
}
if (gc() != 0) {
fillPolygon(gc(),
pts, 3,
Convex, CoordModePrevious);
}
if (gc() != 0)
drawTriangle(gc(), m_arrow_type, 0, 0, width(), height(), m_arrowscale);
}
void ArrowButton::updateTheme(const FbTk::Theme &theme) {
@ -131,7 +93,7 @@ void ArrowButton::updateTheme(const FbTk::Theme &theme) {
const ButtonTheme &btheme = static_cast<const ButtonTheme &>(theme);
m_arrowscale = btheme.scale();
if (m_arrowscale == 0) m_arrowscale = 300; // default is 0 => 300
if (m_arrowscale == 0) m_arrowscale = 250; // default is 0 => 300
else if (m_arrowscale < 100) m_arrowscale = 100; // otherwise clamp
else if (m_arrowscale > 100000) m_arrowscale = 100000; // clamp below overflow when *100
}

View file

@ -29,18 +29,11 @@
/// Displays a arrow on a button
class ArrowButton: public FbTk::Button {
public:
/// type of arrow that should be drawn
enum Type {
LEFT,
RIGHT,
UP,
DOWN
};
ArrowButton(ArrowButton::Type arrow_type, const FbTk::FbWindow &parent,
ArrowButton(FbTk::FbDrawable::TriangleType arrow_type, const FbTk::FbWindow &parent,
int x, int y,
unsigned int width, unsigned int height);
ArrowButton(ArrowButton::Type arrow_type, int screen_num,
ArrowButton(FbTk::FbDrawable::TriangleType arrow_type, int screen_num,
int x, int y,
unsigned int width, unsigned int height);
void clear();
@ -53,7 +46,7 @@ public:
void updateTheme(const FbTk::Theme &theme);
private:
void drawArrow();
Type m_arrow_type;
FbTk::FbDrawable::TriangleType m_arrow_type;
FbTk::EventHandler *m_mouse_handler;
int m_arrowscale;
};

View file

@ -89,6 +89,70 @@ void FbDrawable::fillPolygon(GC gc, XPoint *points, int npoints,
shape, mode);
}
// x, y, width and height define a space within which we're drawing a triangle (centred)
// scale defines number of triangles that'd fit in a space of 100 width x 100 height
// (i.e. 200 = half size, 300 = a third). Its a bit backwards but it allows more flexibility
void FbDrawable::drawTriangle(GC gc, FbDrawable::TriangleType type,
int x, int y, unsigned int width, unsigned int height,
int scale) {
if (drawable() == 0 || gc == 0 || width == 0 || height == 0)
return;
XPoint pts[3];
if (scale < 100) scale = 100; // not bigger than the space allowed
else if (scale > 10000) scale = 10000; // not too small...
int arrowscale_n = scale;
int arrowscale_d = 100;
unsigned int ax = arrowscale_d * width / arrowscale_n;
unsigned int ay = arrowscale_d * height / arrowscale_n;
// if these aren't an even number, left and right arrows end up different
if (type == FbTk::FbDrawable::LEFT ||
type == FbTk::FbDrawable::RIGHT) {
if (( ax % 2 ) == 1) ax--;
if (( ay % 2 ) == 1) ay--;
} else {
if (( ax % 2 ) == 0) ax--;
}
switch (type) {
case FbTk::FbDrawable::LEFT:
// start at the tip
pts[0].x = (width / 2) - (ax / 2); pts[0].y = height / 2;
pts[1].x = ax; pts[1].y = -ay / 2;
pts[2].x = 0; pts[2].y = ay;
break;
case FbTk::FbDrawable::RIGHT:
pts[0].x = (width / 2) + (ax / 2); pts[0].y = height / 2;
pts[1].x = - ax; pts[1].y = ay / 2;
pts[2].x = 0; pts[2].y = - ay;
break;
case FbTk::FbDrawable::UP:
pts[0].x = (width / 2); pts[0].y = (height / 2) - (ay / 2)-1;
pts[1].x = ax / 2; pts[1].y = ay+1;
pts[2].x = - ax; pts[2].y = 0;
break;
case FbTk::FbDrawable::DOWN:
/* I tried and tried, but couldn't get the left diagonal of the down
arrow to be symmetrical with the right (for small widths)!
So we opt for this setup. It is symmetrical with larger widths */
pts[0].x = (width / 2) ; pts[0].y = (height / 2) + (ay / 2);
pts[1].x = -ax/2+1; pts[1].y = -ay;
pts[2].x = ax-1; pts[2].y = 0;
break;
}
// re-centre on the specified points
pts[0].x += x;
pts[0].y += y;
fillPolygon(gc,
pts, 3,
Convex, CoordModePrevious);
}
#ifdef NOT_USED
void FbDrawable::drawPoint(GC gc, int x, int y) {
if (drawable() == 0 || gc == 0)

View file

@ -48,6 +48,20 @@ public:
virtual void fillPolygon(GC gc, XPoint *points, int npoints,
int shape, int mode);
/// type of arrow that should be drawn
enum TriangleType {
LEFT,
RIGHT,
UP,
DOWN
};
// x, y, width and height define a space within which we're drawing a triangle
// scale defines number of triangles that'd fit in a space of 100 width x 100 height
// (i.e. 200 = half size, 300 = a third).
virtual void drawTriangle(GC gc, TriangleType type, int x, int y, unsigned int width, unsigned int height, int scale);
#ifdef NOT_USED
virtual void drawPoint(GC gc, int x, int y);
#endif

View file

@ -216,26 +216,13 @@ void MenuItem::draw(FbDrawable &draw,
break;
case MenuTheme::TRIANGLE:
XPoint tri[3];
if (theme.bulletPos() == FbTk::RIGHT) {
tri[0].x = sel_x + half_w - 2;
tri[0].y = sel_y + half_w - 2;
tri[1].x = 4;
tri[1].y = 2;
tri[2].x = -4;
tri[2].y = 2;
} else { // point the other way
tri[0].x = sel_x + half_w - 2;
tri[0].y = sel_y + half_w;
tri[1].x = 4;
tri[1].y = 2;
tri[2].x = 0;
tri[2].y = -4;
}
draw.fillPolygon(gc, tri, 3, Convex,
CoordModePrevious);
draw.drawTriangle(gc, ((theme.bulletPos() == FbTk::RIGHT)?
FbTk::FbDrawable::RIGHT:
FbTk::FbDrawable::LEFT),
sel_x, sel_y,
item_pm_height,
item_pm_height,
300); // 33% triangle
break;
case MenuTheme::DIAMOND:

View file

@ -112,9 +112,9 @@ ToolbarItem *ToolFactory::create(const std::string &name, const FbTk::FbWindow &
return 0;
// TODO maybe direction of arrows should depend on toolbar layout ?
ArrowButton::Type arrow_type = ArrowButton::LEFT;
FbTk::FbDrawable::TriangleType arrow_type = FbTk::FbDrawable::UP;
if (name == "nextworkspace")
arrow_type = ArrowButton::RIGHT;
arrow_type = FbTk::FbDrawable::DOWN;
ArrowButton *win = new ArrowButton(arrow_type, parent,
0, 0,
@ -131,9 +131,9 @@ ToolbarItem *ToolFactory::create(const std::string &name, const FbTk::FbWindow &
if (*cmd == 0) // we need a command
return 0;
ArrowButton::Type arrow_type = ArrowButton::LEFT;
FbTk::FbDrawable::TriangleType arrow_type = FbTk::FbDrawable::LEFT;
if (name == "nextwindow")
arrow_type = ArrowButton::RIGHT;
arrow_type = FbTk::FbDrawable::RIGHT;
ArrowButton *win = new ArrowButton(arrow_type, parent,
0, 0,

View file

@ -265,20 +265,21 @@ void WinButton::drawType() {
break;
case SHADE:
drawRectangle(gc(), 2, 2, width() - 5 - oddW, 2);
{
int size = width() - 5 - oddW;
drawRectangle(gc(), 2, 2, size, 2);
XPoint points[3];
if (m_listen_to.isShaded()) {
points[1].x = (width() / 2) - 3; points[1].y = 7;
points[2].x = (width() / 2) + 4 - oddW; points[2].y = 7;
points[0].x = (width() / 2); points[0].y = height() / 2 + 2;
} else {
points[0].x = (width() / 2); points[0].y = 6;
points[1].x = (width() / 2) - 4; points[1].y = height() / 2 + 2;
points[2].x = (width() / 2) + 4 - oddW; points[2].y = height() / 2 + 2;
}
fillPolygon(gc(), points, 3, Convex, CoordModeOrigin);
// draw a one-quarter triangle below the rectangle
drawTriangle(gc(), (m_listen_to.isShaded() ?
FbTk::FbDrawable::DOWN:
FbTk::FbDrawable::UP),
4, 6,
size-2, size/2 - 1,
100);
break;
}
case MENUICON:
if (m_icon_pixmap.drawable()) {