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

This commit is contained in:
simonb 2006-03-26 04:02:30 +00:00
parent 872f6a0e1e
commit af74a22845
36 changed files with 658 additions and 212 deletions

View file

@ -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)

View file

@ -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();
}
}

View file

@ -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;

View file

@ -30,6 +30,7 @@
#include "FbWindow.hh"
#include "Command.hh"
#include "Color.hh"
#include "Text.hh"
#include <X11/Xlib.h>
#include <memory>
@ -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

View file

@ -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);
}
}
}

View file

@ -25,6 +25,7 @@
#define FBTK_FBPIXMAP_HH
#include "FbDrawable.hh"
#include "Text.hh"
#include <X11/Xlib.h>
@ -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);

View file

@ -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<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;
*/
}
};

View file

@ -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

View file

@ -25,6 +25,7 @@
#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() { }

View file

@ -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;

View file

@ -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)
)))));
}
};

View file

@ -64,6 +64,7 @@ int doAlignment(int max_width, int bevel, FbTk::Justify justify,
return dx;
}
/// specialization for Justify
template <>
void ThemeItem<FbTk::Justify>::setDefaultValue() {

View file

@ -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

View file

@ -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) {

View file

@ -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

View file

@ -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<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::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();
}

View file

@ -28,6 +28,7 @@
#define FBTK_TEXTURRENDER_HH
#include "Texture.hh"
#include "Text.hh"
#include <X11/Xlib.h>
@ -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;
};

View file

@ -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;

View file

@ -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
};

View file

@ -25,21 +25,28 @@
#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 @@ 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

View file

@ -26,6 +26,7 @@
#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

View file

@ -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;

View file

@ -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; }

View file

@ -41,9 +41,8 @@
#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 @@ 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,12 +1707,48 @@ 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::heightOffset() const {
if (m_tabmode != EXTERNAL || !m_use_tabs)
return 0;
switch (m_screen.getTabPlacement()) {
case TOPLEFT:
case TOPRIGHT:
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 {
@ -1627,10 +1760,7 @@ int FbWinFrame::yOffset() const {
case TOPRIGHT:
return m_tab_container.height() + m_window.borderWidth();
break;
case BOTTOMLEFT:
case BOTTOMRIGHT:
return 0;
break;
}
return 0;
}

View file

@ -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);
//@}

View file

@ -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; }

View file

@ -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,

View file

@ -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);

View file

@ -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; }

View file

@ -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

View file

@ -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

View file

@ -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();

View file

@ -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; }

View file

@ -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"),

View file

@ -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<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

View file

@ -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: "<<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 @@ int main(int argc, char **argv) {
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 @@ int main(int argc, char **argv) {
// 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 @@ int main(int argc, char **argv) {
//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();