From af74a2284551c8511b66d77112c7bf32831c1522 Mon Sep 17 00:00:00 2001 From: simonb Date: Sun, 26 Mar 2006 04:02:30 +0000 Subject: rotated fonts, buttons, containers. Used for tabs for now --- ChangeLog | 16 ++++- src/Container.cc | 81 +++++++++++++++++++--- src/Container.hh | 5 ++ src/FbTk/Button.hh | 2 + src/FbTk/FbPixmap.cc | 56 +++++++++++++--- src/FbTk/FbPixmap.hh | 5 +- src/FbTk/Font.cc | 62 +++-------------- src/FbTk/Font.hh | 19 +++--- src/FbTk/FontImp.hh | 6 +- src/FbTk/ImageControl.cc | 16 +++-- src/FbTk/ImageControl.hh | 22 +++--- src/FbTk/Text.cc | 1 + src/FbTk/Text.hh | 74 ++++++++++++++++++++ src/FbTk/TextButton.cc | 49 +++++++++++--- src/FbTk/TextButton.hh | 13 ++-- src/FbTk/TextureRender.cc | 26 +++++-- src/FbTk/TextureRender.hh | 3 + src/FbTk/XFontImp.cc | 5 +- src/FbTk/XFontImp.hh | 9 +-- src/FbTk/XftFontImp.cc | 102 +++++++++++++++++++++++----- src/FbTk/XftFontImp.hh | 18 +++-- src/FbTk/XmbFontImp.cc | 2 +- src/FbTk/XmbFontImp.hh | 2 +- src/FbWinFrame.cc | 168 ++++++++++++++++++++++++++++++++++++++++------ src/FbWinFrame.hh | 14 ++-- src/FbWinFrameTheme.hh | 1 - src/IconButton.cc | 2 +- src/IconButton.hh | 2 +- src/IconbarTheme.hh | 4 +- src/IconbarTool.hh | 2 +- src/Screen.cc | 13 +--- src/ToolFactory.cc | 2 +- src/ToolFactory.hh | 2 +- src/WinButtonTheme.cc | 2 +- src/WinButtonTheme.hh | 4 +- src/tests/testFont.cc | 58 ++++++++++++---- 36 files changed, 657 insertions(+), 211 deletions(-) diff --git a/ChangeLog b/ChangeLog index c8e727e..b2199a9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -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 @@ Changes for 0.9.15: 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) diff --git a/src/Container.cc b/src/Container.cc index be3a57b..0bec346 100644 --- a/src/Container.cc +++ b/src/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 @@ void Container::insertItem(Item item, int pos) { 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 @@ void Container::setMaxTotalSize(unsigned int size) { 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 @@ void Container::repositionItems() { } 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 @@ void Container::repositionItems() { 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 @@ void Container::repositionItems() { } 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 @@ void Container::clear() { (*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(); + } + +} diff --git a/src/Container.hh b/src/Container.hh index 4014131..20f7048 100644 --- a/src/Container.hh +++ b/src/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 @@ public: 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 @@ public: /// 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; } @@ -103,6 +106,8 @@ public: private: void repositionItems(); + FbTk::Orientation m_orientation; + Alignment m_align; unsigned int m_max_size_per_client; unsigned int m_max_total_size; diff --git a/src/FbTk/Button.hh b/src/FbTk/Button.hh index 02b7b51..fe65f1b 100644 --- a/src/FbTk/Button.hh +++ b/src/FbTk/Button.hh @@ -30,6 +30,7 @@ #include "FbWindow.hh" #include "Command.hh" #include "Color.hh" +#include "Text.hh" #include #include @@ -57,6 +58,7 @@ public: 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 diff --git a/src/FbTk/FbPixmap.cc b/src/FbTk/FbPixmap.cc index 77a65c6..0df087d 100644 --- a/src/FbTk/FbPixmap.cc +++ b/src/FbTk/FbPixmap.cc @@ -201,25 +201,63 @@ void FbPixmap::copy(Pixmap pm, int depth, int screen_num) { 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); + } } } diff --git a/src/FbTk/FbPixmap.hh b/src/FbTk/FbPixmap.hh index f0f51bb..33a64d2 100644 --- a/src/FbTk/FbPixmap.hh +++ b/src/FbTk/FbPixmap.hh @@ -25,6 +25,7 @@ #define FBTK_FBPIXMAP_HH #include "FbDrawable.hh" +#include "Text.hh" #include @@ -49,8 +50,8 @@ public: 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); diff --git a/src/FbTk/Font.cc b/src/FbTk/Font.cc index 2fff39c..a946915 100644 --- a/src/FbTk/Font.cc +++ b/src/FbTk/Font.cc @@ -201,7 +201,6 @@ void Font::shutdown() { 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 @@ void Font::drawText(const FbDrawable &w, int screen, GC gc, 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(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; - */ -} - - }; diff --git a/src/FbTk/Font.hh b/src/FbTk/Font.hh index 76fe63a..720a01e 100644 --- a/src/FbTk/Font.hh +++ b/src/FbTk/Font.hh @@ -38,6 +38,7 @@ #endif // HAVE_ICONV #include "Color.hh" +#include "Text.hh" namespace FbTk { @@ -89,11 +90,13 @@ public: 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 @@ public: */ 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 @@ private: 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 diff --git a/src/FbTk/FontImp.hh b/src/FbTk/FontImp.hh index d659377..bcea7c6 100644 --- a/src/FbTk/FontImp.hh +++ b/src/FbTk/FontImp.hh @@ -25,6 +25,7 @@ #define FBTK_FONTIMP_HH #include "Color.hh" +#include "Font.hh" #include @@ -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() { } diff --git a/src/FbTk/ImageControl.cc b/src/FbTk/ImageControl.cc index 8f05c5d..902bd55 100644 --- a/src/FbTk/ImageControl.cc +++ b/src/FbTk/ImageControl.cc @@ -166,7 +166,7 @@ ImageControl::~ImageControl() { 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 @@ Pixmap ImageControl::searchCache(unsigned int width, unsigned int height, 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 @@ Pixmap ImageControl::searchCache(unsigned int width, unsigned int height, 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::searchCache(unsigned int width, unsigned int height, 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 @@ Pixmap ImageControl::renderImage(unsigned int width, unsigned int height, tmp->pixmap = pixmap; tmp->texture_pixmap = texture.pixmap().drawable(); + tmp->orient = orient; tmp->width = width; tmp->height = height; tmp->count = 1; diff --git a/src/FbTk/ImageControl.hh b/src/FbTk/ImageControl.hh index cec9f05..18ad8db 100644 --- a/src/FbTk/ImageControl.hh +++ b/src/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 @@ public: @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 @@ private: 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 @@ private: 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) + ))))); } }; diff --git a/src/FbTk/Text.cc b/src/FbTk/Text.cc index 052f5b7..b474022 100644 --- a/src/FbTk/Text.cc +++ b/src/FbTk/Text.cc @@ -64,6 +64,7 @@ int doAlignment(int max_width, int bevel, FbTk::Justify justify, return dx; } + /// specialization for Justify template <> void ThemeItem::setDefaultValue() { diff --git a/src/FbTk/Text.hh b/src/FbTk/Text.hh index 977c85a..f04642d 100644 --- a/src/FbTk/Text.hh +++ b/src/FbTk/Text.hh @@ -29,6 +29,9 @@ namespace FbTk { class Font; enum Justify {LEFT, RIGHT, CENTER}; +// clockwise +enum Orientation { ROT0=0, ROT90, ROT180, ROT270 }; + /** Aligns the text after max width and bevel */ @@ -36,6 +39,77 @@ 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 #endif // FBTK_TEXT_HH diff --git a/src/FbTk/TextButton.cc b/src/FbTk/TextButton.cc index ba15280..1d5936c 100644 --- a/src/FbTk/TextButton.cc +++ b/src/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) { @@ -60,6 +62,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) { if (m_text != text) { m_text = text; @@ -68,7 +87,7 @@ void TextButton::setText(const std::string &text) { } } -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,10 +128,16 @@ void TextButton::clearArea(int x, int y, 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) { // (win should always be *this, no need to check) drawText(0, 0, &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 @@ void TextButton::drawText(int x_offset, int y_offset, FbDrawable *drawable) { 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) { diff --git a/src/FbTk/TextButton.hh b/src/FbTk/TextButton.hh index f5738b5..5796a39 100644 --- a/src/FbTk/TextButton.hh +++ b/src/FbTk/TextButton.hh @@ -38,11 +38,12 @@ class Font; 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 @@ public: 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 diff --git a/src/FbTk/TextureRender.cc b/src/FbTk/TextureRender.cc index f2fa35d..7af8f08 100644 --- a/src/FbTk/TextureRender.cc +++ b/src/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 @@ TextureRender::TextureRender(ImageControl &imgctrl, cpc(imgctrl.colorsPerChannel()), cpccpc(cpc * cpc), red(0), green(0), blue(0), + orientation(orient), width(static_cast((w > 0 ? w : 1))), height(static_cast(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::renderGradient(const FbTk::Texture &texture) { } 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() { @@ -728,6 +740,8 @@ Pixmap TextureRender::renderPixmap() { XDestroyImage(image); + pixmap.rotate(orientation); + return pixmap.release(); } diff --git a/src/FbTk/TextureRender.hh b/src/FbTk/TextureRender.hh index d0fee21..14b5547 100644 --- a/src/FbTk/TextureRender.hh +++ b/src/FbTk/TextureRender.hh @@ -28,6 +28,7 @@ #define FBTK_TEXTURRENDER_HH #include "Texture.hh" +#include "Text.hh" #include @@ -43,6 +44,7 @@ class ImageControl; 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 @@ private: 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; }; diff --git a/src/FbTk/XFontImp.cc b/src/FbTk/XFontImp.cc index 5b61555..eeb0830 100644 --- a/src/FbTk/XFontImp.cc +++ b/src/FbTk/XFontImp.cc @@ -79,9 +79,10 @@ bool XFontImp::load(const std::string &fontname) { 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 @@ unsigned int XFontImp::height() const { 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; diff --git a/src/FbTk/XFontImp.hh b/src/FbTk/XFontImp.hh index 06a6279..6b5a34b 100644 --- a/src/FbTk/XFontImp.hh +++ b/src/FbTk/XFontImp.hh @@ -38,12 +38,13 @@ public: 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 @@ private: }; 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 }; diff --git a/src/FbTk/XftFontImp.cc b/src/FbTk/XftFontImp.cc index 1b248fa..a724463 100644 --- a/src/FbTk/XftFontImp.cc +++ b/src/FbTk/XftFontImp.cc @@ -25,21 +25,28 @@ #include "App.hh" #include "FbDrawable.hh" +#include + #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 @@ bool XftFontImp::load(const std::string &name) { 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 @@ void XftFontImp::drawText(const FbDrawable &w, int screen, GC gc, const char *te // 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 @@ void XftFontImp::drawText(const FbDrawable &w, int screen, GC gc, const char *te XftDrawString8(draw, &xftcolor, - m_xftfont, + font, x, y, (XftChar8 *)(text), len); @@ -133,16 +161,19 @@ void XftFontImp::drawText(const FbDrawable &w, int screen, GC gc, const char *te } 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 @@ unsigned int XftFontImp::textWidth(const char * const text, unsigned int len) co #endif //HAVE_XFT_UTF8_STRING XftTextExtents8(disp, - m_xftfont, + font, (XftChar8 *)text, len, &ginfo); @@ -161,12 +192,47 @@ unsigned int XftFontImp::textWidth(const char * const text, unsigned int len) co } 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 diff --git a/src/FbTk/XftFontImp.hh b/src/FbTk/XftFontImp.hh index 21a80b6..f660303 100644 --- a/src/FbTk/XftFontImp.hh +++ b/src/FbTk/XftFontImp.hh @@ -26,6 +26,7 @@ #include #include "FontImp.hh" +#include 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 diff --git a/src/FbTk/XmbFontImp.cc b/src/FbTk/XmbFontImp.cc index c500ba4..e923040 100644 --- a/src/FbTk/XmbFontImp.cc +++ b/src/FbTk/XmbFontImp.cc @@ -184,7 +184,7 @@ bool XmbFontImp::load(const std::string &fontname) { } 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; diff --git a/src/FbTk/XmbFontImp.hh b/src/FbTk/XmbFontImp.hh index cd13b84..9ee5db5 100644 --- a/src/FbTk/XmbFontImp.hh +++ b/src/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; } diff --git a/src/FbWinFrame.cc b/src/FbWinFrame.cc index e9c14c4..160bb2b 100644 --- a/src/FbWinFrame.cc +++ b/src/FbWinFrame.cc @@ -41,9 +41,8 @@ #include -#include #include - +#include using namespace std; FbWinFrame::FbWinFrame(BScreen &screen, FbWinFrameTheme &theme, FbTk::ImageControl &imgctrl, @@ -146,26 +145,63 @@ bool FbWinFrame::setTabMode(TabMode tabmode) { 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 @@ bool FbWinFrame::setTabMode(TabMode tabmode) { 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 @@ bool FbWinFrame::setTabMode(TabMode tabmode) { } 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 @@ void FbWinFrame::moveResize(int x, int y, unsigned int width, unsigned int heigh 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 @@ void FbWinFrame::alignTabs() { 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 @@ void FbWinFrame::reconfigure() { 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 @@ void FbWinFrame::renderTabContainer() { 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::applyButton(FbTk::Button &btn) { } 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 @@ void FbWinFrame::gravityTranslate(int &x, int &y, unsigned int width, unsigned i } } -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; } diff --git a/src/FbWinFrame.hh b/src/FbWinFrame.hh index 900af07..e8003d3 100644 --- a/src/FbWinFrame.hh +++ b/src/FbWinFrame.hh @@ -63,10 +63,10 @@ public: 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 @@ public: 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 @@ public: 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 @@ private: /// 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); //@} diff --git a/src/FbWinFrameTheme.hh b/src/FbWinFrameTheme.hh index 98f8378..0feadd3 100644 --- a/src/FbWinFrameTheme.hh +++ b/src/FbWinFrameTheme.hh @@ -72,7 +72,6 @@ public: 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; } diff --git a/src/IconButton.cc b/src/IconButton.cc index 68988aa..fa85cb2 100644 --- a/src/IconButton.cc +++ b/src/IconButton.cc @@ -134,7 +134,7 @@ private: 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, diff --git a/src/IconButton.hh b/src/IconButton.hh index ad7ff2a..c8ec994 100644 --- a/src/IconButton.hh +++ b/src/IconButton.hh @@ -35,7 +35,7 @@ class IconbarTool; 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); diff --git a/src/IconbarTheme.hh b/src/IconbarTheme.hh index 0964f7a..1a7308a 100644 --- a/src/IconbarTheme.hh +++ b/src/IconbarTheme.hh @@ -41,8 +41,8 @@ public: 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; } diff --git a/src/IconbarTool.hh b/src/IconbarTool.hh index d6a1871..30dac36 100644 --- a/src/IconbarTool.hh +++ b/src/IconbarTool.hh @@ -128,7 +128,7 @@ private: 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 diff --git a/src/Screen.cc b/src/Screen.cc index 01b6d79..e139f74 100644 --- a/src/Screen.cc +++ b/src/Screen.cc @@ -192,7 +192,6 @@ setFromString(const char *strval) { 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 @@ setFromString(const char *strval) { m_value = FbWinFrame::RIGHTTOP; else if (strcasecmp(strval, "RightBottom") == 0) m_value = FbWinFrame::RIGHTBOTTOM; - */ else setDefaultValue(); } @@ -222,7 +220,6 @@ getString() const { case FbWinFrame::BOTTOMRIGHT: return string("BottomRight"); break; -/* case FbWinFrame::LEFTTOP: return string("LeftTop"); break; @@ -235,7 +232,6 @@ getString() const { case FbWinFrame::RIGHTBOTTOM: return string("RightBottom"); break; -*/ } //default string return string("TopLeft"); @@ -1659,16 +1655,13 @@ void BScreen::setupConfigmenu(FbTk::Menu &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, 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, 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, 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 diff --git a/src/ToolFactory.cc b/src/ToolFactory.cc index 0cd01a6..2659b67 100644 --- a/src/ToolFactory.cc +++ b/src/ToolFactory.cc @@ -159,7 +159,7 @@ void ToolFactory::updateThemes() { } -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(); diff --git a/src/ToolFactory.hh b/src/ToolFactory.hh index 503a5e6..7e8edbf 100644 --- a/src/ToolFactory.hh +++ b/src/ToolFactory.hh @@ -47,7 +47,7 @@ public: 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; } diff --git a/src/WinButtonTheme.cc b/src/WinButtonTheme.cc index 5599aba..11041f2 100644 --- a/src/WinButtonTheme.cc +++ b/src/WinButtonTheme.cc @@ -29,7 +29,7 @@ #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"), diff --git a/src/WinButtonTheme.hh b/src/WinButtonTheme.hh index 10b33ab..043f37f 100644 --- a/src/WinButtonTheme.hh +++ b/src/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 @@ private: FbTk::ThemeItem m_stick_pm, m_stick_unfocus_pm, m_stick_pressed_pm; FbTk::ThemeItem m_stuck_pm, m_stuck_unfocus_pm; - const FbWinFrameTheme &m_frame_theme; + FbWinFrameTheme &m_frame_theme; }; #endif // WINBUTTONTHEME_HH diff --git a/src/tests/testFont.cc b/src/tests/testFont.cc index 2ee764c..b382594 100644 --- a/src/tests/testFont.cc +++ b/src/tests/testFont.cc @@ -43,6 +43,7 @@ public: 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 @@ public: 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: "<"<"<"<"<