all repos — fluxbox @ af74a2284551c8511b66d77112c7bf32831c1522

custom fork of the fluxbox windowmanager

rotated fonts, buttons, containers. Used for tabs for now
simonb simonb
commit

af74a2284551c8511b66d77112c7bf32831c1522

parent

872f6a0e1e4230f702ad69fa2d7e10a2fa78b7a3

M ChangeLogChangeLog

@@ -1,5 +1,20 @@

(Format: Year/Month/Day) Changes for 0.9.16: +*06/03/26: + * More external tabs work AND rotated Xft text (Simon) + - new tab positions (LeftTop, LeftBottom, etc) + - TextButtons and Containers can have orientation set on them + - XftFonts store all rotated versions (if used), + so the theme doesn't need to know about it. Pixmaps are also auto-rotated. + - TODO: Update XFontImp rotation code + - Note: many files touched because constness removed from many fonts + FbTk/ Button.hh FbPixmap.hh/cc Font.hh/cc FontImp.hh ImageControl.hh/cc + Text.hh/cc TextButton.hh/cc TextureRender.hh/cc XFontImp.hh/cc + XftFontImp.hh/cc XmbFontImp.hh/cc + Container.hh/cc FbWinFrame.hh/cc FbWinFrameTheme.hh IconButton.hh/cc + IconbarTheme.hh IconbarTool.hh Screen.cc ToolFactory.hh/cc + WinButtonTheme.hh/cc + tests/testFont.cc *06/03/24: * Fix compile error in Theme.cc (sf.net bug #1454204) FbTk/Theme.cc

@@ -200,7 +215,6 @@ * Fixes #1267076, cygwin link problems (Mathias)

src/ScreenResources.cc * Use fbsetroot in Default-Styles (Mathias) data/styles/* -------------------------------------------------------------- Changes for 0.9.14: *05/09/12: * Fixes #1281708, MenuIcon doesnt scale properly (thanx Erik-Jan)
M src/Container.ccsrc/Container.cc

@@ -33,6 +33,7 @@

Container::Container(const FbTk::FbWindow &parent): FbTk::FbWindow(parent, 0, 0, 1, 1, ExposureMask), m_align(RELATIVE), + m_orientation(FbTk::ROT0), m_max_size_per_client(60), m_max_total_size(0), m_selected(0),

@@ -104,6 +105,7 @@ // it must be a child of this window

if (item->parent() != this) return; + item->setOrientation(m_orientation); if (pos >= size() || pos < 0) { m_item_list.push_back(item); } else if (pos == 0) {

@@ -273,6 +275,9 @@

unsigned int old = m_max_total_size; m_max_total_size = size; + repositionItems(); + return; + if (m_max_total_size && width() > m_max_total_size) { resize(m_max_total_size, height()); } else if (!m_max_total_size && old) { // going from restricted to unrestricted

@@ -366,13 +371,25 @@ void Container::repositionItems() {

if (empty() || m_update_lock) return; - //!! TODO vertical position + /** + NOTE: all calculations here are done in non-rotated space + */ unsigned int max_width_per_client = maxWidthPerClient(); unsigned int borderW = m_item_list.front()->borderWidth(); unsigned int num_items = m_item_list.size(); - unsigned int total_width = width(); + unsigned int total_width; + unsigned int cur_width; + unsigned int height; + // unrotate + if (m_orientation == FbTk::ROT0 || m_orientation == FbTk::ROT180) { + total_width = cur_width = width(); + height = this->height(); + } else { + total_width = cur_width = this->height(); + height = width(); + } // if we have a max total size, then we must also resize ourself // within that bound

@@ -387,12 +404,20 @@ total_width = (max_width_per_client + borderW) * num_items - borderW;

} else max_width_per_client = 1; } - if (total_width != width()) { + + if (total_width != cur_width) { // calling Container::resize here risks infinite loops - if (align == RIGHT) - FbTk::FbWindow::moveResize(x() - (total_width - width()), y(), total_width, height()); - else - FbTk::FbWindow::resize(total_width, height()); + unsigned int neww = total_width, newh = height; + translateSize(m_orientation, neww, newh); + if (align == RIGHT || m_orientation == FbTk::ROT270) { + int deltax = - (total_width - cur_width); + int deltay = 0; + FbTk::translateCoords(m_orientation, deltax, deltay, total_width, height); + + FbTk::FbWindow::moveResize(x() + deltax, y() + deltay, neww, newh); + } else { + FbTk::FbWindow::resize(neww, newh); + } } }

@@ -410,6 +435,8 @@ direction = -1;

next_x = total_width - max_width_per_client - borderW; } + int tmpx, tmpy; + unsigned int tmpw, tmph; for (; it != it_end; ++it, next_x += direction*(max_width_per_client + borderW + extra)) { // we only need to do error stuff with alignment RELATIVE if (rounding_error != 0 && align == RELATIVE) {

@@ -418,11 +445,20 @@ extra = 1;

} else { extra = 0; } + // rotate the x and y coords + tmpx = next_x; + tmpy = -borderW; + tmpw = max_width_per_client + extra; + tmph = height; + + FbTk::translateCoords(m_orientation, tmpx, tmpy, total_width, height); + FbTk::translatePosition(m_orientation, tmpx, tmpy, tmpw, tmph); + FbTk::translateSize(m_orientation, tmpw, tmph); + // resize each clients including border in size - (*it)->moveResize(next_x, - -borderW, - max_width_per_client + extra, - height()); + (*it)->moveResize(tmpx, tmpy, + tmpw, tmph); + // moveresize does a clear }

@@ -476,3 +512,26 @@ for (; it != it_end; ++it)

(*it)->clear(); } + +void Container::setOrientation(FbTk::Orientation orient) { + if (m_orientation == orient) + return; + + ItemList::iterator it = m_item_list.begin(); + ItemList::iterator it_end = m_item_list.end(); + for (; it != it_end; ++it) + (*it)->setOrientation(orient); + + if ((m_orientation == FbTk::ROT0 || m_orientation == FbTk::ROT180) && + (orient == FbTk::ROT90 || orient == FbTk::ROT270) || + (m_orientation == FbTk::ROT90 || m_orientation == FbTk::ROT270) && + (orient == FbTk::ROT0 || orient == FbTk::ROT180)) { + // flip width and height + m_orientation = orient; + resize(height(), width()); + } else { + m_orientation = orient; + repositionItems(); + } + +}
M src/Container.hhsrc/Container.hh

@@ -28,6 +28,7 @@

#include "FbTk/FbWindow.hh" #include "FbTk/EventHandler.hh" #include "FbTk/NotCopyable.hh" +#include "FbTk/Text.hh" // for Orientation namespace FbTk { class Button;

@@ -66,6 +67,7 @@ void setSelected(int index);

void setMaxSizePerClient(unsigned int size); void setMaxTotalSize(unsigned int size); void setAlignment(Alignment a); + void setOrientation(FbTk::Orientation orient); Item back() { return m_item_list.back(); }

@@ -83,6 +85,7 @@ bool tryButtonReleaseEvent(XButtonEvent &event);

/// accessors inline Alignment alignment() const { return m_align; } + inline FbTk::Orientation orientation() const { return m_orientation; } inline int size() const { return m_item_list.size(); } inline bool empty() const { return m_item_list.empty(); } inline const Item& selected() const { return m_selected; }

@@ -102,6 +105,8 @@ void clear(); // clear all windows

private: void repositionItems(); + + FbTk::Orientation m_orientation; Alignment m_align; unsigned int m_max_size_per_client;
M src/FbTk/Button.hhsrc/FbTk/Button.hh

@@ -30,6 +30,7 @@ #include "RefCount.hh"

#include "FbWindow.hh" #include "Command.hh" #include "Color.hh" +#include "Text.hh" #include <X11/Xlib.h> #include <memory>

@@ -57,6 +58,7 @@ /// sets background pixmap, this will override background color

virtual void setBackgroundPixmap(Pixmap pm); /// sets background color virtual void setBackgroundColor(const Color &color); + virtual bool setOrientation(FbTk::Orientation orient) { return orient == FbTk::ROT0; } /** @name eventhandlers
M src/FbTk/FbPixmap.ccsrc/FbTk/FbPixmap.cc

@@ -201,25 +201,63 @@

XFreeGC(display(), gc); } -void FbPixmap::rotate() { +void FbPixmap::rotate(FbTk::Orientation orient) { + if (orient == ROT0) + return; + + unsigned int oldw = width(), oldh = height(); + unsigned int neww = oldw, newh = oldh; + translateSize(orient, neww, newh); // make an image copy XImage *src_image = XGetImage(display(), drawable(), 0, 0, // pos - width(), height(), // size + oldw, oldh, // size ~0, // plane mask ZPixmap); // format // reverse height/width for new pixmap - FbPixmap new_pm(drawable(), height(), width(), depth()); + FbPixmap new_pm(drawable(), neww, newh, depth()); GContext gc(drawable()); - // copy new area - for (unsigned int y = 0; y < height(); ++y) { - for (unsigned int x = 0; x < width(); ++x) { - gc.setForeground(XGetPixel(src_image, x, y)); - // revers coordinates - XDrawPoint(display(), new_pm.drawable(), gc.gc(), y, x); + if (orient == ROT180) { + unsigned int srcx, srcy, destx, desty; + for (srcy = 0, desty = oldh; srcy < oldh; ++srcy, --desty) { + for (srcx = 0, destx = oldw; srcx < oldw; ++srcx, --destx) { + gc.setForeground(XGetPixel(src_image, srcx, srcy)); + XDrawPoint(display(), new_pm.drawable(), gc.gc(), destx, desty); + } + } + } else { + // need to flip x and y + + // set start, end and direction based on rotation + // NOTE that startx etc are in the direction of the OLD pixmap + unsigned int startx, starty; + int dirx, diry; + switch (orient) { + case ROT90: + startx = neww-1; + starty = 0; + dirx = -1; + diry = 1; + break; + case ROT270: + startx = 0; + starty = newh-1; + dirx = 1; + diry = -1; + break; + } + + + // copy new area + unsigned int srcx, srcy, destx, desty; + for (srcy = 0, destx = startx; srcy < oldh; ++srcy, destx+=dirx) { + for (srcx = 0, desty = starty; srcx < oldw; ++srcx, desty+=diry) { + gc.setForeground(XGetPixel(src_image, srcx, srcy)); + XDrawPoint(display(), new_pm.drawable(), gc.gc(), destx, desty); + } } }
M src/FbTk/FbPixmap.hhsrc/FbTk/FbPixmap.hh

@@ -25,6 +25,7 @@ #ifndef FBTK_FBPIXMAP_HH

#define FBTK_FBPIXMAP_HH #include "FbDrawable.hh" +#include "Text.hh" #include <X11/Xlib.h>

@@ -49,8 +50,8 @@ virtual ~FbPixmap();

void copy(const FbPixmap &the_copy); void copy(Pixmap pixmap, int depth_convert, int screen_num); - /// rotates the pixmap 90 deg, not implemented! - void rotate(); + /// rotates the pixmap to specified orientation (assumes ROT0 now) + void rotate(FbTk::Orientation orient); /// scales the pixmap to specified size void scale(unsigned int width, unsigned int height); void resize(unsigned int width, unsigned int height);
M src/FbTk/Font.ccsrc/FbTk/Font.cc

@@ -201,7 +201,6 @@ }

Font::Font(const char *name): m_fontimp(0), - m_rotated(false), m_shadow(false), m_shadow_color("black", DefaultScreen(App::instance()->display())), m_shadow_offx(2), m_shadow_offy(2), m_halo(false), m_halo_color("white", DefaultScreen(App::instance()->display())),

@@ -361,9 +360,13 @@ int Font::descent() const {

return m_fontimp->descent(); } +bool Font::validOrientation(FbTk::Orientation orient) { + return m_fontimp->validOrientation(orient); +} + void Font::drawText(const FbDrawable &w, int screen, GC gc, const char *text, size_t len, int x, int y, - bool rotate) const { + Orientation orient) const { if (text == 0 || len == 0) return;

@@ -391,69 +394,26 @@ FbTk::GContext shadow_gc(w);

shadow_gc.setForeground(m_shadow_color); first_run = false; drawText(w, screen, shadow_gc.gc(), real_text, len, - x + m_shadow_offx, y + m_shadow_offy, rotate); + x + m_shadow_offx, y + m_shadow_offy, orient); first_run = true; } else if (m_halo) { FbTk::GContext halo_gc(w); halo_gc.setForeground(m_halo_color); first_run = false; - drawText(w, screen, halo_gc.gc(), real_text, len, x + 1, y + 1, rotate); - drawText(w, screen, halo_gc.gc(), real_text, len, x - 1, y + 1, rotate); - drawText(w, screen, halo_gc.gc(), real_text, len, x - 1, y - 1, rotate); - drawText(w, screen, halo_gc.gc(), real_text, len, x + 1, y - 1, rotate); + drawText(w, screen, halo_gc.gc(), real_text, len, x + 1, y + 1, orient); + drawText(w, screen, halo_gc.gc(), real_text, len, x - 1, y + 1, orient); + drawText(w, screen, halo_gc.gc(), real_text, len, x - 1, y - 1, orient); + drawText(w, screen, halo_gc.gc(), real_text, len, x + 1, y - 1, orient); first_run = true; } } - if (!rotate && isRotated()) { - // if this was called with request to not rotated the text - // we just forward it to the implementation that handles rotation - // currently just XFontImp - // Using dynamic_cast just temporarly until there's a better solution - // to put in FontImp - try { - XFontImp *font = dynamic_cast<XFontImp *>(m_fontimp); - font->setRotate(false); // disable rotation temporarly - - font->drawText(w, screen, gc, real_text, len, x, y); - font->setRotate(true); // enable rotation - } catch (std::bad_cast &bc) { - // draw normal... - m_fontimp->drawText(w, screen, gc, real_text, len, x, y); - } - - } else - m_fontimp->drawText(w, screen, gc, real_text, len, x, y); + m_fontimp->drawText(w, screen, gc, real_text, len, x, y, orient); if (rtext != 0) delete[] rtext; } - -void Font::rotate(float angle) { -/* TODO: reimplement rotated text -#ifdef USE_XFT - // if we are rotated and we are changing to horiz text - // and we were antialiased before we rotated then change to XftFontImp - if (isRotated() && angle == 0 && !m_xftfontstr.empty()) - m_fontimp.reset(new XftFontImp(m_fontstr.c_str(),s_utf8mode)); -#endif // USE_XFT - // change to a font imp that handles rotated fonts (i.e just XFontImp at the moment) - // if we're going to rotate this font - if (angle != 0 && !isRotated()) { - m_fontimp.reset(new XFontImp(m_fontstr.c_str())); - if (!m_fontimp->loaded()) // if it failed to load font, try default font fixed - m_fontimp->load("fixed"); - } - - //Note: only XFontImp implements FontImp::rotate - m_fontimp->rotate(angle); - - m_rotated = (angle == 0 ? false : true); - m_angle = angle; - */ -} - };
M src/FbTk/Font.hhsrc/FbTk/Font.hh

@@ -38,6 +38,7 @@ #include <iconv.h>

#endif // HAVE_ICONV #include "Color.hh" +#include "Text.hh" namespace FbTk {

@@ -89,11 +90,13 @@ unsigned int textWidth(const char * const text, unsigned int size) const;

unsigned int height() const; int ascent() const; int descent() const; + /** - Rotate font in any angle - (currently only 90 degrees supported and just XFont implementation) + Returns whether we can draw this font in the given orientation. + (will instantiate that orientation, so do plan to use it...) + @param orient the orientation to test */ - void rotate(float angle); + bool validOrientation(FbTk::Orientation orient); /** Draws text to drawable

@@ -108,11 +111,8 @@ @param rotate if the text should be drawn rotated (if it's rotated before)

*/ void drawText(const FbDrawable &w, int screen, GC gc, const char *text, size_t len, - int x, int y, bool rotate=true) const; - /// @return true if the font is rotated, else false - bool isRotated() const { return m_rotated; } - /// @return rotated angle - float angle() const { return m_angle; } + int x, int y, FbTk::Orientation orient = ROT0) const; + bool hasShadow() const { return m_shadow; } bool hasHalo() const { return m_halo; } private:

@@ -123,8 +123,7 @@

static bool s_multibyte; ///< if the fontimp should be a multibyte font static bool s_utf8mode; ///< should the font use utf8 font imp - bool m_rotated; ///< wheter we're rotated or not - float m_angle; ///< rotation angle + int m_angle; ///< rotation angle bool m_shadow; ///< shadow text Color m_shadow_color; ///< shadow color int m_shadow_offx; ///< offset y for shadow
M src/FbTk/FontImp.hhsrc/FbTk/FontImp.hh

@@ -25,6 +25,7 @@ #ifndef FBTK_FONTIMP_HH

#define FBTK_FONTIMP_HH #include "Color.hh" +#include "Font.hh" #include <X11/Xlib.h>

@@ -43,13 +44,14 @@ class FontImp {

public: virtual ~FontImp() { } virtual bool load(const std::string &name) = 0; - virtual void drawText(const FbDrawable &w, int screen, GC gc, const char *text, size_t len, int x, int y) const = 0; + virtual void drawText(const FbDrawable &w, int screen, GC gc, const char *text, size_t len, int x, int y, FbTk::Orientation orient) const = 0; virtual unsigned int textWidth(const char * const text, unsigned int size) const = 0; + virtual bool validOrientation(FbTk::Orientation orient) { return orient == ROT0; } virtual int ascent() const = 0; virtual int descent() const = 0; virtual unsigned int height() const = 0; virtual bool loaded() const = 0; - virtual void rotate(float angle) { } // by default, no rotate support + virtual void rotate(int angle) { } // by default, no rotate support virtual bool utf8() const { return false; }; protected: FontImp() { }
M src/FbTk/ImageControl.ccsrc/FbTk/ImageControl.cc

@@ -166,7 +166,7 @@ }

Pixmap ImageControl::searchCache(unsigned int width, unsigned int height, - const Texture &text) const { + const Texture &text, FbTk::Orientation orient) const { if (text.pixmap().drawable() != None) { // do comparsion with width/height and texture_pixmap

@@ -174,7 +174,9 @@ CacheList::iterator it = cache.begin();

CacheList::iterator it_end = cache.end(); for (; it != it_end; ++it) { if ((*it)->texture_pixmap == text.pixmap().drawable() && - (*it)->width == width && (*it)->height == height && + (*it)->orient == orient && + (*it)->width == width && + (*it)->height == height && (*it)->texture == text.type()) { (*it)->count++; return (*it)->pixmap;

@@ -196,6 +198,7 @@ CacheList::iterator it = cache.begin();

CacheList::iterator it_end = cache.end(); for (; it != it_end; ++it) { if (((*it)->width == width) && + ((*it)->orient == orient) && ((*it)->height == height) && ((*it)->texture == text.type()) && ((*it)->pixel1 == text.color().pixel())) {

@@ -217,19 +220,21 @@ }

Pixmap ImageControl::renderImage(unsigned int width, unsigned int height, - const FbTk::Texture &texture) { + const FbTk::Texture &texture, + FbTk::Orientation orient) { if (texture.type() & FbTk::Texture::PARENTRELATIVE) return ParentRelative; // search cache first - Pixmap pixmap = searchCache(width, height, texture); + Pixmap pixmap = searchCache(width, height, texture, orient); if (pixmap) { return pixmap; // return cache item } // render new image - TextureRender image(*this, width, height, m_colors, m_num_colors); + + TextureRender image(*this, width, height, orient, m_colors, m_num_colors); pixmap = image.render(texture); if (pixmap) {

@@ -239,6 +244,7 @@ Cache *tmp = new Cache;

tmp->pixmap = pixmap; tmp->texture_pixmap = texture.pixmap().drawable(); + tmp->orient = orient; tmp->width = width; tmp->height = height; tmp->count = 1;
M src/FbTk/ImageControl.hhsrc/FbTk/ImageControl.hh

@@ -27,6 +27,8 @@

#ifndef FBTK_IMAGECONTROL_HH #define FBTK_IMAGECONTROL_HH +// actually, Text is rather tool like, that's where orientation comes from +#include "Text.hh" #include "Texture.hh" #include "Timer.hh" #include "NotCopyable.hh"

@@ -61,7 +63,8 @@ @param src_texture texture type to render

@return pixmap of the rendered image, on failure None */ Pixmap renderImage(unsigned int width, unsigned int height, - const FbTk::Texture &src_texture); + const FbTk::Texture &src_texture, + Orientation orient = ROT0); void installRootColormap(); void removeImage(Pixmap thepix);

@@ -79,7 +82,7 @@ /**

Search cache for a specific pixmap @return None if no cache was found */ - Pixmap searchCache(unsigned int width, unsigned int height, const Texture &text) const; + Pixmap searchCache(unsigned int width, unsigned int height, const Texture &text, Orientation orient) const; void createColorTable(); bool m_dither;

@@ -109,19 +112,20 @@

typedef struct Cache { Pixmap pixmap; Pixmap texture_pixmap; + Orientation orient; unsigned int count, width, height; unsigned long pixel1, pixel2, texture; } Cache; struct ltCacheEntry { bool operator()(const Cache* s1, const Cache* s2) const { - return (s1->width < s2->width || s1->width == s2->width && - (s1->height < s2->height || s1->height == s2->height && - (s1->texture < s2->texture || s1->texture == s2->texture && - s1->pixel1 < s2->pixel1 || s1->pixel1 == s2->pixel1 && - (s1->texture & FbTk::Texture::GRADIENT) && - s1->pixel2 < s2->pixel2) - )); + return (s1->orient < s2->orient || s1->orient == s2->orient + && (s1->width < s2->width || s1->width == s2->width + && (s1->height < s2->height || s1->height == s2->height + && (s1->texture < s2->texture || s1->texture == s2->texture + && (s1->pixel1 < s2->pixel1 || s1->pixel1 == s2->pixel1 + && ((s1->texture & FbTk::Texture::GRADIENT) && s1->pixel2 < s2->pixel2) + ))))); } };
M src/FbTk/Text.ccsrc/FbTk/Text.cc

@@ -64,6 +64,7 @@

return dx; } + /// specialization for Justify template <> void ThemeItem<FbTk::Justify>::setDefaultValue() {
M src/FbTk/Text.hhsrc/FbTk/Text.hh

@@ -29,12 +29,86 @@

class Font; enum Justify {LEFT, RIGHT, CENTER}; +// clockwise +enum Orientation { ROT0=0, ROT90, ROT180, ROT270 }; + /** Aligns the text after max width and bevel */ int doAlignment(int max_width, int bevel, FbTk::Justify justify, const FbTk::Font &font, const char * const text, unsigned int textlen, unsigned int &newlen); + +/** + There are 3 interesting translations: + 1) Coords = simple rotation of coordinates + 2) Position = adjusting (x,y) coordinates to use to position a box with X coords + 3) Size = swapping of width and height if necessary + */ + + +// translate coordinates from ROT0 into different orientations +// coords are relative to rot0 0,0 position +// Need width and height of the area being rotated (in ROT0 coords) + +inline void translateCoords(Orientation orient, int &x, int &y, unsigned int w, unsigned int h) { + + int orig_x = x; + int orig_y = y; + + switch(orient) { + case ROT0: + break; + case ROT90: + x = h - orig_y; + y = orig_x; + break; + case ROT180: + x = w - orig_x; + y = h - orig_y; + break; + case ROT270: + x = orig_y; + y = w - orig_x; + break; + } + +} + +// When positioning an X11 box inside another area, we need to +// relocate the x,y coordinates +inline void translatePosition(Orientation orient, int &x, int &y, unsigned int w, unsigned int h) { + + int orig_x = x; + int orig_y = y; + + switch(orient) { + case ROT0: + break; + case ROT90: + x -= h; + break; + case ROT180: + x -= w; + y -= h; + break; + case ROT270: + y -= w; + break; + } + +} + +inline void translateSize(Orientation orient, unsigned int &w, unsigned int &h) { + if (orient == ROT0 || orient == ROT180) + return; + + unsigned int tmp; + tmp = w; + w = h; + h = tmp; + +} } // end namespace FbTk
M src/FbTk/TextButton.ccsrc/FbTk/TextButton.cc

@@ -28,16 +28,18 @@

namespace FbTk { TextButton::TextButton(const FbTk::FbWindow &parent, - const FbTk::Font &font, + FbTk::Font &font, const std::string &text): FbTk::Button(parent, 0, 0, 10, 10), m_font(&font), m_text(text), - m_justify(FbTk::LEFT), m_bevel(1), + m_justify(FbTk::LEFT), + m_orientation(FbTk::ROT0), + m_bevel(1), m_left_padding(0), m_right_padding(0) { - setRenderer(*this); + setRenderer(*this); } void TextButton::resize(unsigned int width, unsigned int height) {

@@ -58,6 +60,23 @@ }

void TextButton::setJustify(FbTk::Justify just) { m_justify = just; +} + +bool TextButton::setOrientation(FbTk::Orientation orient) { + if (!m_font->validOrientation(orient)) + return false; + + if ((m_orientation == FbTk::ROT0 || m_orientation == FbTk::ROT180) && + (orient == FbTk::ROT90 || orient == FbTk::ROT270) || + (m_orientation == FbTk::ROT90 || m_orientation == FbTk::ROT270) && + (orient == FbTk::ROT0 || orient == FbTk::ROT180)) { + // flip width and height + m_orientation = orient; + resize(height(), width()); + } else { + m_orientation = orient; + } + return true; } void TextButton::setText(const std::string &text) {

@@ -68,7 +87,7 @@ clear();

} } -void TextButton::setFont(const FbTk::Font &font) { +void TextButton::setFont(FbTk::Font &font) { // no need to set new font if it's the same if (&font == m_font) return;

@@ -109,8 +128,14 @@ if (backgroundPixmap() == ParentRelative)

drawText(0, 0, this); } + unsigned int TextButton::textWidth() const { return font().textWidth(text().c_str(), text().size()); +} + +unsigned int TextButton::textHeight() const { + return font().height(); + } void TextButton::renderForeground(FbWindow &win, FbDrawable &drawable) {

@@ -122,7 +147,10 @@ void TextButton::drawText(int x_offset, int y_offset, FbDrawable *drawable) {

unsigned int textlen = text().size(); // do text alignment - int align_x = FbTk::doAlignment(width() - x_offset - m_left_padding - m_right_padding, + unsigned int textw = width(), texth = height(); + translateSize(m_orientation, textw, texth); + + int align_x = FbTk::doAlignment(textw - x_offset - m_left_padding - m_right_padding, bevel(), justify(), font(),

@@ -130,17 +158,22 @@ text().c_str(), text().size(),

textlen); // return new text lne // center text by default - int center_pos = height()/2 + font().ascent()/2 - 1; + int center_pos = texth/2 + font().ascent()/2 - 1; + + int textx = align_x + x_offset + m_left_padding; + int texty = center_pos + y_offset; if (drawable == 0) drawable = this; + // give it ROT0 style coords + translateCoords(m_orientation, textx, texty, textw, texth); + font().drawText(*drawable, screenNumber(), gc(), // graphic context text().c_str(), textlen, // string and string size - align_x + x_offset + m_left_padding, center_pos + y_offset); // position - + textx, texty, m_orientation); // position } void TextButton::exposeEvent(XExposeEvent &event) {
M src/FbTk/TextButton.hhsrc/FbTk/TextButton.hh

@@ -38,11 +38,12 @@ /// Displays a text on a button

class TextButton: public FbTk::Button, FbTk::FbWindowRenderer { public: TextButton(const FbTk::FbWindow &parent, - const FbTk::Font &font, const std::string &text); + FbTk::Font &font, const std::string &text); void setJustify(FbTk::Justify just); + bool setOrientation(FbTk::Orientation orient); void setText(const std::string &text); - void setFont(const FbTk::Font &font); + void setFont(FbTk::Font &font); void setBevel(int bevel); void setTextPadding(unsigned int padding); void setTextPaddingLeft(unsigned int leftpadding);

@@ -65,8 +66,9 @@ void renderForeground(FbDrawable &drawable);

inline FbTk::Justify justify() const { return m_justify; } inline const std::string &text() const { return m_text; } - inline const FbTk::Font &font() const { return *m_font; } + inline FbTk::Font &font() const { return *m_font; } unsigned int textWidth() const; + unsigned int textHeight() const; int bevel() const { return m_bevel; } unsigned int leftPadding() const { return m_left_padding; } unsigned int rightPadding() const { return m_right_padding; }

@@ -77,10 +79,11 @@ protected:

virtual void drawText(int x_offset, int y_offset, FbDrawable *drawable_override); private: - const FbTk::Font *m_font; + FbTk::Font *m_font; std::string m_text; FbTk::Justify m_justify; - + FbTk::Orientation m_orientation; + int m_bevel; unsigned int m_left_padding; ///< space between buttonborder and text unsigned int m_right_padding; ///< space between buttonborder and text
M src/FbTk/TextureRender.ccsrc/FbTk/TextureRender.cc

@@ -52,6 +52,7 @@ namespace FbTk {

TextureRender::TextureRender(ImageControl &imgctrl, unsigned int w, unsigned int h, + FbTk::Orientation orient, XColor *_colors, size_t num_colors): control(imgctrl), colors(_colors),

@@ -59,6 +60,7 @@ ncolors(ncolors),

cpc(imgctrl.colorsPerChannel()), cpccpc(cpc * cpc), red(0), green(0), blue(0), + orientation(orient), width(static_cast<signed>((w > 0 ? w : 1))), height(static_cast<signed>(h > 0 ? h : 1)), xtable(0), ytable(0) {

@@ -231,6 +233,9 @@ Pixmap TextureRender::renderGradient(const FbTk::Texture &texture) {

bool inverted = false; + // invert our width and height if necessary + translateSize(orientation, width, height); + using namespace FbTk; interlaced = texture.type() & Texture::INTERLACED;

@@ -281,23 +286,30 @@

} Pixmap TextureRender::renderPixmap(const FbTk::Texture &src_texture) { - if (width != src_texture.pixmap().width() || - height != src_texture.pixmap().height()) { + unsigned int tmpw = width, tmph = height; + // we are given width and height in rotated form, we + // unrotate it here to render it + translateSize(orientation, tmpw, tmph); + if (tmpw != src_texture.pixmap().width() || + tmph != src_texture.pixmap().height()) { // copy src_texture's pixmap and // scale/tile to fit our size FbPixmap new_pm(src_texture.pixmap()); if ((src_texture.type() & Texture::TILED)) { - new_pm.tile(width,height); + new_pm.tile(tmpw,tmph); } else { - new_pm.scale(width, height); + new_pm.scale(tmpw, tmph); } - + new_pm.rotate(orientation); return new_pm.release(); } // return copy of pixmap - return FbPixmap(src_texture.pixmap()).release(); + FbPixmap pm_copy = FbPixmap(src_texture.pixmap()); + pm_copy.rotate(orientation); + + return pm_copy.release(); } XImage *TextureRender::renderXImage() {

@@ -727,6 +739,8 @@ image->data = 0;

} XDestroyImage(image); + + pixmap.rotate(orientation); return pixmap.release(); }
M src/FbTk/TextureRender.hhsrc/FbTk/TextureRender.hh

@@ -28,6 +28,7 @@ #ifndef FBTK_TEXTURRENDER_HH

#define FBTK_TEXTURRENDER_HH #include "Texture.hh" +#include "Text.hh" #include <X11/Xlib.h>

@@ -43,6 +44,7 @@ */

class TextureRender { public: TextureRender(ImageControl &ic, unsigned int width, unsigned int height, + Orientation orient = ROT0, XColor *_colors=0, size_t num_colors=0); ~TextureRender(); /// render to pixmap

@@ -94,6 +96,7 @@ int red_offset, green_offset, blue_offset, red_bits, green_bits, blue_bits,

ncolors, cpc, cpccpc; unsigned char *red, *green, *blue; const unsigned char *red_table, *green_table, *blue_table; + Orientation orientation; unsigned int width, height; unsigned int *xtable, *ytable; };
M src/FbTk/XFontImp.ccsrc/FbTk/XFontImp.cc

@@ -79,9 +79,10 @@

return true; } -void XFontImp::drawText(const FbDrawable &w, int screen, GC gc, const char *text, size_t len, int x, int y) const { +void XFontImp::drawText(const FbDrawable &w, int screen, GC gc, const char *text, size_t len, int x, int y, FbTk::Orientation orient) const { if (m_fontstruct == 0) return; + // use roated font functions? if (m_rotfont != 0 && m_rotate) { drawRotText(w.drawable(), screen, gc, text, len, x, y);

@@ -110,7 +111,7 @@

return m_fontstruct->ascent + m_fontstruct->descent; } -void XFontImp::rotate(float angle) { +void XFontImp::rotate(int angle) { //we must have a font loaded before we rotate if (m_fontstruct == 0 || m_fontstruct->per_char == 0) return;
M src/FbTk/XFontImp.hhsrc/FbTk/XFontImp.hh

@@ -38,12 +38,13 @@ ~XFontImp();

bool load(const std::string &filename); unsigned int textWidth(const char * const text, unsigned int size) const; unsigned int height() const; - float angle() const { return m_angle; } + int angle() const { return m_angle; } int ascent() const; int descent() const { return m_fontstruct ? m_fontstruct->descent : 0; } - void drawText(const FbDrawable &w, int screen, GC gc, const char *text, size_t len, int x, int y) const; + void drawText(const FbDrawable &w, int screen, GC gc, const char *text, size_t len, int x, int y, FbTk::Orientation orient) const; + bool loaded() const { return m_fontstruct != 0; } - void rotate(float angle); + void rotate(int angle); /// enable/disable rotation witout alloc/dealloc rotfont structures void setRotate(bool val) { m_rotate = val; } private:

@@ -79,7 +80,7 @@ XRotCharStruct per_char[95];

}; XRotFontStruct *m_rotfont; ///< rotated font structure XFontStruct *m_fontstruct; ///< X font structure - float m_angle; ///< the rotated angle + int m_angle; ///< the rotated angle bool m_rotate; ///< used to disable/enable rotation temprarly without reallocating m_rotfont };
M src/FbTk/XftFontImp.ccsrc/FbTk/XftFontImp.cc

@@ -25,21 +25,28 @@ #include "XftFontImp.hh"

#include "App.hh" #include "FbDrawable.hh" +#include <math.h> + #ifdef HAVE_CONFIG_H #include "config.h" #endif //HAVE_CONFIG_H namespace FbTk { -XftFontImp::XftFontImp(const char *name, bool utf8):m_xftfont(0), - m_utf8mode(utf8) { +XftFontImp::XftFontImp(const char *name, bool utf8): + m_utf8mode(utf8), m_name("") { + + for (int r = ROT0; r <= ROT270; r++) + m_xftfonts[r] = 0; + if (name != 0) load(name); } XftFontImp::~XftFontImp() { - if (m_xftfont != 0) - XftFontClose(App::instance()->display(), m_xftfont); + for (int r = ROT0; r <= ROT270; r++) + if (m_xftfonts[r] != 0) + XftFontClose(App::instance()->display(), m_xftfonts[r]); } bool XftFontImp::load(const std::string &name) {

@@ -54,18 +61,39 @@ if (newxftfont == 0)

return false; } - // destroy old font and set new - if (m_xftfont != 0) - XftFontClose(disp, m_xftfont); + // destroy all old fonts and set new + for (int r = ROT0; r <= ROT270; r++) + if (m_xftfonts[r] != 0) + XftFontClose(App::instance()->display(), m_xftfonts[r]); - m_xftfont = newxftfont; + m_xftfonts[ROT0] = newxftfont; + m_name = name; return true; } -void XftFontImp::drawText(const FbDrawable &w, int screen, GC gc, const char *text, size_t len, int x, int y) const { - if (m_xftfont == 0) +void XftFontImp::drawText(const FbDrawable &w, int screen, GC gc, const char *text, size_t len, int x, int y, FbTk::Orientation orient) const { + if (m_xftfonts[orient] == 0) return; + + // we adjust y slightly so that the baseline is in the right spot + // (it is offset one by rotation >=180 degrees) + switch (orient) { + case ROT0: + break; + case ROT90: + break; + case ROT180: + x+=1; + y+=1; + break; + case ROT270: + y+=1; + break; + } + + XftFont *font = m_xftfonts[orient]; + XftDraw *draw = XftDrawCreate(w.display(), w.drawable(), DefaultVisual(w.display(), screen),

@@ -101,13 +129,13 @@ // check the string size,

// if the size is zero we use the XftDrawString8 function instead. XGlyphInfo ginfo; XftTextExtentsUtf8(w.display(), - m_xftfont, + m_xftfonts[ROT0], (XftChar8 *)text, len, &ginfo); if (ginfo.xOff != 0) { XftDrawStringUtf8(draw, &xftcolor, - m_xftfont, + font, x, y, (XftChar8 *)(text), len); XftColorFree(w.display(),

@@ -121,7 +149,7 @@ #endif // HAVE_XFT_UTF8_STRING

XftDrawString8(draw, &xftcolor, - m_xftfont, + font, x, y, (XftChar8 *)(text), len);

@@ -133,16 +161,19 @@ XftDrawDestroy(draw);

} unsigned int XftFontImp::textWidth(const char * const text, unsigned int len) const { - if (m_xftfont == 0) + if (m_xftfonts[ROT0] == 0) return 0; XGlyphInfo ginfo; Display* disp = App::instance()->display(); + XftFont *font = m_xftfonts[ROT0]; + + #ifdef HAVE_XFT_UTF8_STRING if (m_utf8mode) { XftTextExtentsUtf8(disp, - m_xftfont, + font, (XftChar8 *)text, len, &ginfo); if (ginfo.xOff != 0)

@@ -153,7 +184,7 @@ }

#endif //HAVE_XFT_UTF8_STRING XftTextExtents8(disp, - m_xftfont, + font, (XftChar8 *)text, len, &ginfo);

@@ -161,12 +192,47 @@ return ginfo.xOff;

} unsigned int XftFontImp::height() const { - if (m_xftfont == 0) + if (m_xftfonts[ROT0] == 0) return 0; - return m_xftfont->height; + else + return m_xftfonts[ROT0]->height; //m_xftfont->ascent + m_xftfont->descent; // curiously, fonts seem to have a smaller height, but the "height" // is specified within the actual font, so it must be right, right? } + +bool XftFontImp::validOrientation(FbTk::Orientation orient) { + if (orient == ROT0 || m_xftfonts[orient]) + return true; + + if (m_xftfonts[ROT0] == 0) + return false; + + // otherwise, try to load that orientation + // radians is actually anti-clockwise, so we reverse it + double radians = -(orient) * 90 * M_PI / 180; + + XftMatrix matrix; + XftMatrixInit(&matrix); + XftMatrixRotate(&matrix, cos(radians), sin(radians)); + + Display *disp = App::instance()->display(); + + XftPattern * pattern = XftNameParse(m_name.c_str()); + XftPatternAddMatrix(pattern, XFT_MATRIX, &matrix); + XftResult result; + XftPattern * foundpat = XftFontMatch(disp, 0, pattern, &result); + XftPatternDestroy(pattern); + XftFont * new_font = XftFontOpenPattern(disp, foundpat); + + if (new_font == 0) + return false; + + m_xftfonts[orient] = new_font; + + return true; +} + + }; // end namespace FbTk
M src/FbTk/XftFontImp.hhsrc/FbTk/XftFontImp.hh

@@ -26,6 +26,7 @@ #define FBTK_XFTFONTIMP_HH

#include <X11/Xft/Xft.h> #include "FontImp.hh" +#include <string> namespace FbTk {

@@ -35,16 +36,23 @@ public:

XftFontImp(const char *fontname, bool utf8); ~XftFontImp(); bool load(const std::string &name); - void drawText(const FbDrawable &w, int screen, GC gc, const char *text, size_t len, int x, int y) const; + void drawText(const FbDrawable &w, int screen, GC gc, const char *text, size_t len, int x, int y , FbTk::Orientation orient) const; unsigned int textWidth(const char * const text, unsigned int len) const; unsigned int height() const; - int ascent() const { return m_xftfont ? m_xftfont->ascent : 0; } - int descent() const { return m_xftfont ? m_xftfont->descent : 0; } - bool loaded() const { return m_xftfont != 0; } + int ascent() const { return m_xftfonts[0] ? m_xftfonts[0]->ascent : 0; } + int descent() const { return m_xftfonts[0] ? m_xftfonts[0]->descent : 0; } + bool loaded() const { return m_xftfonts[0] != 0; } bool utf8() const { return m_utf8mode; } + bool validOrientation(FbTk::Orientation orient); + private: - XftFont *m_xftfont; + XftFont *m_xftfonts[4]; // 4 possible orientations + // rotated xft fonts don't give proper extents info, so we keep the "real" + // one around for it bool m_utf8mode; + + std::string m_name; + int m_angle; }; } // end namespace FbTk
M src/FbTk/XmbFontImp.ccsrc/FbTk/XmbFontImp.cc

@@ -184,7 +184,7 @@ return true;

} void XmbFontImp::drawText(const FbDrawable &w, int screen, GC gc, const char *text, - size_t len, int x, int y) const { + size_t len, int x, int y, FbTk::Orientation orient) const { if (m_fontset == 0) return;
M src/FbTk/XmbFontImp.hhsrc/FbTk/XmbFontImp.hh

@@ -36,7 +36,7 @@ public:

XmbFontImp(const char *fontname, bool utf8); ~XmbFontImp(); bool load(const std::string &name); - virtual void drawText(const FbDrawable &w, int screen, GC gc, const char *text, size_t len, int x, int y) const; + virtual void drawText(const FbDrawable &w, int screen, GC gc, const char *text, size_t len, int x, int y, FbTk::Orientation orient) const; unsigned int textWidth(const char * const text, unsigned int len) const; unsigned int height() const; int ascent() const { return m_setextents ? -m_setextents->max_ink_extent.y : 0; }
M src/FbWinFrame.ccsrc/FbWinFrame.cc

@@ -41,9 +41,8 @@ #endif // SHAPE

#include <algorithm> -#include <iostream> #include <X11/X.h> - +#include <iostream> using namespace std; FbWinFrame::FbWinFrame(BScreen &screen, FbWinFrameTheme &theme, FbTk::ImageControl &imgctrl,

@@ -146,26 +145,63 @@ GrabModeSync, GrabModeSync, None, None);

XUngrabButton(m_tab_container.display(), Button1, Mod1Mask|Mod2Mask|Mod3Mask, m_tab_container.window()); int tabx, taby; + unsigned int maxtotal; switch (m_screen.getTabPlacement()) { case TOPLEFT: m_tab_container.setAlignment(Container::LEFT); + m_tab_container.setOrientation(FbTk::ROT0); tabx = x(); taby = y() - yOffset(); + maxtotal = m_window.width(); break; case TOPRIGHT: m_tab_container.setAlignment(Container::RIGHT); + m_tab_container.setOrientation(FbTk::ROT0); tabx = x() + width() - m_tab_container.width(); taby = y() - yOffset(); + maxtotal = m_window.width(); + break; + case LEFTTOP: + m_tab_container.setAlignment(Container::RIGHT); + m_tab_container.setOrientation(FbTk::ROT270); + tabx = x() - xOffset(); + taby = y(); + maxtotal = m_window.height(); + break; + case LEFTBOTTOM: + m_tab_container.setAlignment(Container::LEFT); + m_tab_container.setOrientation(FbTk::ROT270); + tabx = x() - xOffset(); + taby = y() + height() - m_tab_container.height(); + maxtotal = m_window.height(); + break; + case RIGHTTOP: + m_tab_container.setAlignment(Container::LEFT); + m_tab_container.setOrientation(FbTk::ROT90); + tabx = x() + width(); + taby = y(); + maxtotal = m_window.height(); + break; + case RIGHTBOTTOM: + m_tab_container.setAlignment(Container::RIGHT); + m_tab_container.setOrientation(FbTk::ROT90); + tabx = x() + width(); + taby = y() + height() - m_tab_container.height(); + maxtotal = m_window.height(); break; case BOTTOMLEFT: m_tab_container.setAlignment(Container::LEFT); + m_tab_container.setOrientation(FbTk::ROT0); tabx = x(); taby = y() + height() + m_window.borderWidth(); + maxtotal = m_window.width(); break; case BOTTOMRIGHT: m_tab_container.setAlignment(Container::RIGHT); + m_tab_container.setOrientation(FbTk::ROT0); tabx = x() + width() - m_tab_container.width(); taby = y() + height() + m_window.borderWidth(); + maxtotal = m_window.width(); break; }

@@ -176,7 +212,7 @@ }

m_tab_container.setMaxSizePerClient(m_screen.getTabWidth()); m_tab_container.setUpdateLock(false); - m_tab_container.setMaxTotalSize(window().width()); + m_tab_container.setMaxTotalSize(maxtotal); renderTabContainer(); applyTabContainer();

@@ -192,6 +228,7 @@ }

} else { m_tab_container.setAlignment(Container::RELATIVE); + m_tab_container.setOrientation(FbTk::ROT0); if (m_tab_container.parent()->window() == m_screen.rootWindow().window()) { m_layeritem.removeWindow(m_tab_container); m_tab_container.reparent(m_titlebar, m_label.x(), m_label.y());

@@ -329,8 +366,19 @@ if (move || resize && m_screen.getTabPlacement() != TOPLEFT)

alignTabs(); if (resize) { - if (m_tabmode == EXTERNAL) - m_tab_container.setMaxTotalSize(width); + if (m_tabmode == EXTERNAL) { + switch(m_screen.getTabPlacement()) { + case LEFTTOP: + case RIGHTTOP: + case LEFTBOTTOM: + case RIGHTBOTTOM: + m_tab_container.setMaxTotalSize(height); + break; + default: + m_tab_container.setMaxTotalSize(width); + break; + } + } reconfigure(); } }

@@ -339,7 +387,18 @@ void FbWinFrame::quietMoveResize(int x, int y,

unsigned int width, unsigned int height) { m_window.moveResize(x, y, width, height); if (m_tabmode == EXTERNAL) { - m_tab_container.setMaxTotalSize(width); + + switch(m_screen.getTabPlacement()) { + case LEFTTOP: + case RIGHTTOP: + case LEFTBOTTOM: + case RIGHTBOTTOM: + m_tab_container.setMaxTotalSize(height); + break; + default: + m_tab_container.setMaxTotalSize(width); + break; + } alignTabs(); } }

@@ -357,18 +416,42 @@

int tabx = 0, taby = 0; switch (m_screen.getTabPlacement()) { case TOPLEFT: + m_tab_container.setOrientation(FbTk::ROT0); tabx = x(); taby = y() - yOffset(); break; case TOPRIGHT: + m_tab_container.setOrientation(FbTk::ROT0); tabx = x() + width() - m_tab_container.width(); taby = y() - yOffset(); break; + case LEFTTOP: + m_tab_container.setOrientation(FbTk::ROT270); + tabx = x() - xOffset(); + taby = y(); + break; + case LEFTBOTTOM: + m_tab_container.setOrientation(FbTk::ROT270); + tabx = x() - xOffset(); + taby = y() + height() - m_tab_container.height(); + break; + case RIGHTTOP: + m_tab_container.setOrientation(FbTk::ROT90); + tabx = x() + width(); + taby = y(); + break; + case RIGHTBOTTOM: + m_tab_container.setOrientation(FbTk::ROT90); + tabx = x() + width(); + taby = y() + height() - m_tab_container.height(); + break; case BOTTOMLEFT: + m_tab_container.setOrientation(FbTk::ROT0); tabx = x(); taby = y() + height() + m_window.borderWidth(); break; case BOTTOMRIGHT: + m_tab_container.setOrientation(FbTk::ROT0); tabx = x() + width() - m_tab_container.width(); taby = y() + height() + m_window.borderWidth(); break;

@@ -899,7 +982,21 @@ } else

m_titlebar.lower(); if (m_tabmode == EXTERNAL) { - m_tab_container.resize(m_tab_container.width(), buttonHeight()); + unsigned int neww, newh; + switch (m_screen.getTabPlacement()) { + case TOPLEFT: + case TOPRIGHT: + case BOTTOMLEFT: + case BOTTOMRIGHT: + neww = m_tab_container.width(); + newh = buttonHeight(); + break; + default: + neww = buttonHeight(); + newh = m_tab_container.height(); + break; + } + m_tab_container.resize(neww, newh); alignTabs(); }

@@ -1112,23 +1209,23 @@ }

render(m_theme.labelFocusTexture(), m_tabcontainer_focused_color, m_tabcontainer_focused_pm, - m_tab_container.width(), m_tab_container.height()); + m_tab_container.width(), m_tab_container.height(), m_tab_container.orientation()); render(m_theme.labelUnfocusTexture(), m_tabcontainer_unfocused_color, m_tabcontainer_unfocused_pm, - m_tab_container.width(), m_tab_container.height()); + m_tab_container.width(), m_tab_container.height(), m_tab_container.orientation()); render(m_theme.labelFocusTexture(), m_labelbutton_focused_color, m_labelbutton_focused_pm, - m_tab_container.width(), m_tab_container.height()); + m_tab_container.width(), m_tab_container.height(), m_tab_container.orientation()); render(m_theme.labelUnfocusTexture(), m_labelbutton_unfocused_color, m_labelbutton_unfocused_pm, - m_tab_container.width(), m_tab_container.height()); + m_tab_container.width(), m_tab_container.height(), m_tab_container.orientation()); render(m_theme.labelActiveTexture(), m_labelbutton_active_color, m_labelbutton_active_pm, - m_tab_container.width(), m_tab_container.height()); + m_tab_container.width(), m_tab_container.height(), m_tab_container.orientation()); }

@@ -1338,14 +1435,14 @@

} void FbWinFrame::render(const FbTk::Texture &tex, FbTk::Color &col, Pixmap &pm, - unsigned int w, unsigned int h) { + unsigned int w, unsigned int h, FbTk::Orientation orient) { Pixmap tmp = pm; if (!tex.usePixmap()) { pm = None; col = tex.color(); } else { - pm = m_imagectrl.renderImage(w, h, tex); + pm = m_imagectrl.renderImage(w, h, tex, orient); } if (tmp)

@@ -1610,27 +1707,60 @@ move(x, y);

} } -int FbWinFrame::heightOffset() const { +int FbWinFrame::widthOffset() const { if (m_tabmode != EXTERNAL || !m_use_tabs) return 0; // same height offset for top and bottom tabs - return m_tab_container.height() + m_window.borderWidth(); + switch (m_screen.getTabPlacement()) { + case LEFTTOP: + case RIGHTTOP: + case LEFTBOTTOM: + case RIGHTBOTTOM: + return m_tab_container.width() + m_window.borderWidth(); + break; + } + return 0; } -int FbWinFrame::yOffset() const { +int FbWinFrame::heightOffset() const { if (m_tabmode != EXTERNAL || !m_use_tabs) return 0; switch (m_screen.getTabPlacement()) { case TOPLEFT: case TOPRIGHT: - return m_tab_container.height() + m_window.borderWidth(); - break; case BOTTOMLEFT: case BOTTOMRIGHT: + return m_tab_container.height() + m_window.borderWidth(); + break; + } + return 0; +} + +int FbWinFrame::xOffset() const { + if (m_tabmode != EXTERNAL || !m_use_tabs) return 0; + + switch (m_screen.getTabPlacement()) { + case LEFTTOP: + case LEFTBOTTOM: + return m_tab_container.width() + m_window.borderWidth(); break; } + return 0; +} + +int FbWinFrame::yOffset() const { + if (m_tabmode != EXTERNAL || !m_use_tabs) + return 0; + + switch (m_screen.getTabPlacement()) { + case TOPLEFT: + case TOPRIGHT: + return m_tab_container.height() + m_window.borderWidth(); + break; + } + return 0; }
M src/FbWinFrame.hhsrc/FbWinFrame.hh

@@ -63,10 +63,10 @@ /// Toolbar placement on the screen

enum TabPlacement{ // top and bottom placement TOPLEFT = 1, BOTTOMLEFT, - TOPRIGHT, BOTTOMRIGHT + TOPRIGHT, BOTTOMRIGHT, // left and right placement -// LEFTBOTTOM, LEFTTOP, -// RIGHTBOTTOM, RIGHTTOP + LEFTBOTTOM, LEFTTOP, + RIGHTBOTTOM, RIGHTTOP };

@@ -200,9 +200,9 @@ inline unsigned int width() const { return m_window.width(); }

inline unsigned int height() const { return m_window.height(); } // extra bits for tabs - inline int xOffset() const { return 0; } + int xOffset() const; int yOffset() const; - inline int widthOffset() const { return 0; } + int widthOffset() const; int heightOffset() const; inline const FbTk::FbWindow &window() const { return m_window; }

@@ -229,7 +229,7 @@ inline FbTk::FbWindow &gripRight() { return m_grip_right; }

inline const FbTk::TextButton *currentLabel() const { return m_current_label; } inline bool focused() const { return m_focused; } inline bool isShaded() const { return m_shaded; } - inline const FbWinFrameTheme &theme() const { return m_theme; } + inline FbWinFrameTheme &theme() const { return m_theme; } /// @return titlebar height unsigned int titlebarHeight() const { return m_titlebar.height(); } /// @return size of button

@@ -259,7 +259,7 @@ void renderButtons(); // subset of renderTitlebar - don't call directly

/// renders to pixmap or sets color void render(const FbTk::Texture &tex, FbTk::Color &col, Pixmap &pm, - unsigned int width, unsigned int height); + unsigned int width, unsigned int height, FbTk::Orientation orient = FbTk::ROT0); //@}
M src/FbWinFrameTheme.hhsrc/FbWinFrameTheme.hh

@@ -72,7 +72,6 @@

const FbTk::Color &buttonFocuscolor() const { return *m_button_focus_color; } const FbTk::Color &buttonUnfocuscolor() const { return *m_button_unfocus_color; } //@} - const FbTk::Font &font() const { return *m_font; } FbTk::Font &font() { return *m_font; } FbTk::Justify justify() const { return *m_textjustify; }
M src/IconButton.ccsrc/IconButton.cc

@@ -134,7 +134,7 @@

IconButton::IconButton(const IconbarTool& tool, const FbTk::FbWindow &parent, - const FbTk::Font &font, FluxboxWindow &win): + FbTk::Font &font, FluxboxWindow &win): FbTk::TextButton(parent, font, win.winClient().title()), m_win(win), m_icon_window(*this, 1, 1, 1, 1,
M src/IconButton.hhsrc/IconButton.hh

@@ -35,7 +35,7 @@

class IconButton: public FbTk::TextButton, public FbTk::Observer { public: IconButton(const IconbarTool& tool, const FbTk::FbWindow &parent, - const FbTk::Font &font, FluxboxWindow &window); + FbTk::Font &font, FluxboxWindow &window); virtual ~IconButton(); void exposeEvent(XExposeEvent &event);
M src/IconbarTheme.hhsrc/IconbarTheme.hh

@@ -41,8 +41,8 @@ bool fallback(FbTk::ThemeItem_base &item);

void setAntialias(bool antialias); - const TextTheme &focusedText() const { return m_focused_text; } - const TextTheme &unfocusedText() const { return m_unfocused_text; } + TextTheme &focusedText() { return m_focused_text; } + TextTheme &unfocusedText() { return m_unfocused_text; } const BorderTheme &focusedBorder() const { return m_focused_border; } const BorderTheme &unfocusedBorder() const { return m_unfocused_border; }
M src/IconbarTool.hhsrc/IconbarTool.hh

@@ -128,7 +128,7 @@ void timedRender();

BScreen &m_screen; Container m_icon_container; - const IconbarTheme &m_theme; + IconbarTheme &m_theme; // cached pixmaps Pixmap m_focused_pm, m_unfocused_pm; // some are a fraction bigger due to rounding
M src/Screen.ccsrc/Screen.cc

@@ -192,7 +192,6 @@ else if (strcasecmp(strval, "TopRight")==0)

m_value = FbWinFrame::TOPRIGHT; else if (strcasecmp(strval, "BottomRight")==0) m_value = FbWinFrame::BOTTOMRIGHT; - /* else if (strcasecmp(strval, "LeftTop") == 0) m_value = FbWinFrame::LEFTTOP; else if (strcasecmp(strval, "LeftBottom") == 0)

@@ -201,7 +200,6 @@ else if (strcasecmp(strval, "RightTop") == 0)

m_value = FbWinFrame::RIGHTTOP; else if (strcasecmp(strval, "RightBottom") == 0) m_value = FbWinFrame::RIGHTBOTTOM; - */ else setDefaultValue(); }

@@ -222,7 +220,6 @@ break;

case FbWinFrame::BOTTOMRIGHT: return string("BottomRight"); break; -/* case FbWinFrame::LEFTTOP: return string("LeftTop"); break;

@@ -235,7 +232,6 @@ break;

case FbWinFrame::RIGHTBOTTOM: return string("RightBottom"); break; -*/ } //default string return string("TopLeft");

@@ -1659,16 +1655,13 @@ Placements place_menu;

// menu is 2 wide, 2 down place_menu.push_back(PlacementP(_FBTEXT(Align, TopLeft, "Top Left", "Top Left"), FbWinFrame::TOPLEFT)); + place_menu.push_back(PlacementP(_FBTEXT(Align, LeftTop, "Left Top", "Left Top"), FbWinFrame::LEFTTOP)); + place_menu.push_back(PlacementP(_FBTEXT(Align, LeftBottom, "Left Bottom", "Left Bottom"), FbWinFrame::LEFTBOTTOM)); place_menu.push_back(PlacementP(_FBTEXT(Align, BottomLeft, "Bottom Left", "Bottom Left"), FbWinFrame::BOTTOMLEFT)); place_menu.push_back(PlacementP(_FBTEXT(Align, TopRight, "Top Right", "Top Right"), FbWinFrame::TOPRIGHT)); - place_menu.push_back(PlacementP(_FBTEXT(Align, BottomRight, "Bottom Right", "Bottom Right"), FbWinFrame::BOTTOMRIGHT)); - -/* - place_menu.push_back(PlacementP(_FBTEXT(Align, LeftTop, "Left Top", "Left Top"), FbWinFrame::LEFTTOP)); - place_menu.push_back(PlacementP(_FBTEXT(Align, LeftBottom, "Left Bottom", "Left Bottom"), FbWinFrame::LEFTBOTTOM)); place_menu.push_back(PlacementP(_FBTEXT(Align, RightTop, "Right Top", "Right Top"), FbWinFrame::RIGHTTOP)); place_menu.push_back(PlacementP(_FBTEXT(Align, RightBottom, "Right Bottom", "Right Bottom"), FbWinFrame::RIGHTBOTTOM)); -*/ + place_menu.push_back(PlacementP(_FBTEXT(Align, BottomRight, "Bottom Right", "Bottom Right"), FbWinFrame::BOTTOMRIGHT)); tabplacement_menu->setMinimumSublevels(2); // create items in sub menu
M src/ToolFactory.ccsrc/ToolFactory.cc

@@ -159,7 +159,7 @@ m_workspace_theme->reconfigTheme();

} -int ToolFactory::maxFontHeight() const { +int ToolFactory::maxFontHeight() { unsigned int max_height = 0; if (max_height < m_clock_theme.font().height()) max_height = m_clock_theme.font().height();
M src/ToolFactory.hhsrc/ToolFactory.hh

@@ -47,7 +47,7 @@ virtual ~ToolFactory() { }

ToolbarItem *create(const std::string &name, const FbTk::FbWindow &parent, Toolbar &tbar); void updateThemes(); - int maxFontHeight() const; + int maxFontHeight(); inline const BScreen &screen() const { return m_screen; } inline BScreen &screen() { return m_screen; }
M src/WinButtonTheme.ccsrc/WinButtonTheme.cc

@@ -29,7 +29,7 @@ #include "FbTk/PixmapWithMask.hh"

#include "FbWinFrameTheme.hh" -WinButtonTheme::WinButtonTheme(int screen_num, const FbWinFrameTheme &frame_theme): +WinButtonTheme::WinButtonTheme(int screen_num, FbWinFrameTheme &frame_theme): FbTk::Theme(screen_num), m_close_pm(*this, "window.close.pixmap", "Window.Close.Pixmap"), m_close_unfocus_pm(*this, "window.close.unfocus.pixmap", "Window.Close.Unfocus.Pixmap"),
M src/WinButtonTheme.hhsrc/WinButtonTheme.hh

@@ -31,7 +31,7 @@ class FbWinFrameTheme;

class WinButtonTheme: public FbTk::Theme { public: - WinButtonTheme(int screen_num, const FbWinFrameTheme &frame_theme); + WinButtonTheme(int screen_num, FbWinFrameTheme &frame_theme); ~WinButtonTheme(); void reconfigTheme();

@@ -99,7 +99,7 @@ FbTk::ThemeItem<FbTk::PixmapWithMask> m_title_focus_pm, m_title_unfocus_pm;

FbTk::ThemeItem<FbTk::PixmapWithMask> m_stick_pm, m_stick_unfocus_pm, m_stick_pressed_pm; FbTk::ThemeItem<FbTk::PixmapWithMask> m_stuck_pm, m_stuck_unfocus_pm; - const FbWinFrameTheme &m_frame_theme; + FbWinFrameTheme &m_frame_theme; }; #endif // WINBUTTONTHEME_HH
M src/tests/testFont.ccsrc/tests/testFont.cc

@@ -43,6 +43,7 @@ m_win(DefaultScreen(display()),

0, 0, 640, 480, KeyPressMask | ExposureMask) { m_background = background; m_foreground = foreground; + m_orient = FbTk::ROT0; m_win.show(); m_win.setBackgroundColor(FbTk::Color(background.c_str(), m_win.screenNumber())); FbTk::EventManager::instance()->add(*this, m_win);

@@ -70,43 +71,70 @@ }

void redraw() { size_t text_w = m_font.textWidth(m_text.c_str(), m_text.size()); + int mult = 1; + if (m_orient == FbTk::ROT180) + mult = -1; size_t text_h = m_font.height(); - int x = 640/2 - text_w/2; - int y = 480/2 - text_h/2; + int x = 640/2 - mult* text_w/2; + int y = 480/2 - mult*text_h/2; m_win.clear(); FbTk::GContext wingc(m_win.drawable()); - + + int bx1 = 0; + int by1 = 0; + int bx2 = text_w; + int by2 = 0; + int tmp; + + switch (m_orient) { + case FbTk::ROT90: + by2 = bx2; + bx2 = 0; + break; + case FbTk::ROT180: + bx2 = -bx2; + break; + case FbTk::ROT270: + by2 = -bx2; + bx2 = 0; + break; + } + +/* m_win.drawLine(wingc.gc(), x, y + m_font.descent(), x + text_w, y + m_font.descent()); m_win.drawLine(wingc.gc(), x, y - text_h, x + text_w, y - text_h); +*/ + // draw the baseline in red wingc.setForeground(FbTk::Color("red", m_win.screenNumber())); m_win.drawLine(wingc.gc(), - x, y, x + text_w, y); + x + bx1, y + by1, x + bx2, y+by2); wingc.setForeground(FbTk::Color(m_foreground.c_str(), m_win.screenNumber())); - //cerr<<"text width: "<<m_font.textWidth(m_text.c_str(), m_text.size())<<endl; + cerr<<"text size "<<text_w<<"x"<<text_h<<endl; m_font.drawText(m_win, 0, wingc.gc(), m_text.c_str(), m_text.size(), - x, y); + x, y, m_orient); } FbTk::Font &font() { return m_font; } - void setText(const std::string& text) { m_text = text; } + void setText(const std::string& text, const FbTk::Orientation orient) { m_text = text; m_orient = orient; } private: string m_foreground, m_background; FbTk::FbWindow m_win; FbTk::Font m_font; + FbTk::Orientation m_orient; string m_text; }; int main(int argc, char **argv) { //bool antialias = false; - bool rotate = false; + FbTk::Orientation orient = FbTk::ROT0; bool xft = false; string fontname(""); string displayname("");

@@ -122,8 +150,8 @@ } else if (strcmp("-display", argv[a]) == 0 && a + 1 < argc) {

displayname = argv[++a]; } else if (strcmp("-text", argv[a]) == 0 && a + 1 < argc) { text = argv[++a]; - } else if (strcmp("-rotate", argv[a]) == 0) { - rotate = true; + } else if (strcmp("-orient", argv[a]) == 0) { + orient = (FbTk::Orientation) (atoi(argv[++a]) % 4); } else if (strcmp("-bg", argv[a]) == 0 && a + 1 < argc) { background = argv[++a]; } else if (strcmp("-fg", argv[a]) == 0 && a + 1 < argc) {

@@ -134,7 +162,7 @@ cerr<<"-font <fontname>"<<endl;

// cerr<<"-antialias"<<endl; cerr<<"-display <display>"<<endl; cerr<<"-text <text>"<<endl; - cerr<<"-rotate"<<endl; + cerr<<"-orient"<<endl; cerr<<"-fg <foreground color>"<<endl; cerr<<"-bg <background color>"<<endl; cerr<<"-h"<<endl;

@@ -148,10 +176,12 @@ App app(displayname.c_str(), foreground, background);

//app.font().setAntialias(antialias); if (!app.font().load(fontname.c_str())) cerr<<"Failed to load: "<<fontname<<endl; + if (orient && !app.font().validOrientation(orient)) { + cerr<<"Orientation not valid ("<<orient<<")"<<endl; + orient = FbTk::ROT0; + } cerr<<"Setting text: "<<text<<endl; - app.setText(text); - if (rotate) - app.font().rotate(90); + app.setText(text, orient); app.redraw(); app.eventLoop();