fluxbox/src/FbWinFrame.cc

1090 lines
33 KiB
C++
Raw Normal View History

2003-01-05 22:14:10 +00:00
// FbWinFrame.cc for Fluxbox Window Manager
// Copyright (c) 2003 Henrik Kinnunen (fluxgen at users.sourceforge.net)
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
2003-08-25 13:15:53 +00:00
// $Id: FbWinFrame.cc,v 1.42 2003/08/25 13:15:53 rathnor Exp $
2003-01-05 22:14:10 +00:00
#include "FbWinFrame.hh"
2003-08-19 16:15:32 +00:00
#include "FbTk/ImageControl.hh"
#include "FbTk/EventManager.hh"
#include "FbTk/TextButton.hh"
#include "FbTk/App.hh"
2003-08-24 11:19:45 +00:00
#include "FbTk/Compose.hh"
2003-08-19 16:15:32 +00:00
2003-07-10 11:36:21 +00:00
#include "FbWinFrameTheme.hh"
2003-02-17 22:45:42 +00:00
#ifdef SHAPE
2003-07-10 11:36:21 +00:00
#include "Shape.hh"
2003-02-17 22:45:42 +00:00
#endif // SHAPE
2003-01-05 22:14:10 +00:00
2003-08-24 11:19:45 +00:00
2003-04-14 15:01:55 +00:00
#include <algorithm>
2003-01-05 22:14:10 +00:00
#include <iostream>
using namespace std;
2003-02-17 22:57:52 +00:00
FbWinFrame::FbWinFrame(FbWinFrameTheme &theme, FbTk::ImageControl &imgctrl,
int screen_num, int x, int y,
2003-01-05 22:14:10 +00:00
unsigned int width, unsigned int height):
m_theme(theme),
m_imagectrl(imgctrl),
m_window(screen_num, x, y, width, height, ButtonPressMask | ButtonReleaseMask |
ButtonMotionMask | EnterWindowMask, true),
m_titlebar(m_window, 0, 0, 100, 16,
ButtonPressMask | ButtonReleaseMask |
ButtonMotionMask | ExposureMask |
EnterWindowMask | LeaveWindowMask),
m_label(m_titlebar, 0, 0, 100, 16,
ButtonPressMask | ButtonReleaseMask |
ButtonMotionMask | ExposureMask |
EnterWindowMask | LeaveWindowMask),
m_grip_right(m_window, 0, 0, 10, 4,
ButtonPressMask | ButtonReleaseMask |
ButtonMotionMask | ExposureMask |
EnterWindowMask | LeaveWindowMask),
m_grip_left(m_window, 0, 0, 10, 4,
ButtonPressMask | ButtonReleaseMask |
ButtonMotionMask | ExposureMask |
EnterWindowMask | LeaveWindowMask),
m_handle(m_window, 0, 0, 100, 5,
ButtonPressMask | ButtonReleaseMask |
ButtonMotionMask | ExposureMask |
EnterWindowMask | LeaveWindowMask),
m_clientarea(m_window, 0, 0, 100, 100,
ButtonPressMask | ButtonReleaseMask |
ButtonMotionMask | ExposureMask |
EnterWindowMask | LeaveWindowMask),
m_bevel(1),
m_use_titlebar(true),
m_use_handle(true),
m_focused(false),
2003-05-01 13:19:36 +00:00
m_visible(false),
2003-02-15 01:54:54 +00:00
m_button_pm(0),
2003-07-10 11:36:21 +00:00
m_themelistener(*this),
m_shape(new Shape(m_window, theme.shapePlace())) {
2003-02-15 01:54:54 +00:00
theme.addListener(m_themelistener);
2003-01-05 22:14:10 +00:00
init();
}
2003-04-14 15:01:55 +00:00
2003-01-05 22:14:10 +00:00
/*
2003-01-09 22:08:27 +00:00
FbWinFrame::FbWinFrame(FbWinFrameTheme &theme, FbTk::ImageControl &imgctrl, const FbTk::FbWindow &parent, int x, int y,
2003-01-05 22:14:10 +00:00
unsigned int width, unsigned int height):
m_theme(theme),
m_imagectrl(imgctrl),
m_window(parent, x, y, width, height, ExposureMask | StructureNotifyMask),
m_titlebar(m_window, 0, 0, 100, 16,
ExposureMask | ButtonPressMask | ButtonReleaseMask),
m_label(m_titlebar, 0, 0, 100, 16,
ExposureMask | ButtonPressMask | ButtonReleaseMask),
m_grip_right(m_window, 0, 0, 100, 100, ExposureMask | ButtonPressMask | ButtonReleaseMask),
m_grip_left(m_window, 0, 0, 100, 100, ExposureMask | ButtonPressMask | ButtonReleaseMask),
m_handle(m_window, 0, 0, 100, 100, ExposureMask | ButtonPressMask | ButtonReleaseMask),
m_clientarea(m_window, 0, 0, 100, 100, SubstructureRedirectMask),
m_bevel(1),
m_use_titlebar(true),
m_use_handles(true),
m_button_pm(0) {
init();
}
*/
FbWinFrame::~FbWinFrame() {
removeEventHandler();
removeAllButtons();
}
bool FbWinFrame::setOnClickTitlebar(FbTk::RefCount<FbTk::Command> &ref, int mousebutton_num,
bool double_click, bool pressed) {
// find mousebutton_num
if (mousebutton_num < 1 || mousebutton_num > 5)
return false;
if (double_click)
m_commands[mousebutton_num - 1].double_click = ref;
else {
if (pressed)
m_commands[mousebutton_num - 1].click_pressed = ref;
else
m_commands[mousebutton_num - 1].click = ref;
}
return true;
}
2003-01-05 22:14:10 +00:00
void FbWinFrame::hide() {
m_window.hide();
2003-05-01 13:19:36 +00:00
m_visible = false;
2003-01-05 22:14:10 +00:00
}
void FbWinFrame::show() {
2003-05-01 13:19:36 +00:00
m_visible = true;
reconfigure();
2003-01-05 22:14:10 +00:00
m_window.showSubwindows();
m_window.show();
}
/**
Toggle shade state, and resize window
*/
void FbWinFrame::shade() {
2003-02-20 23:21:23 +00:00
if (!m_use_titlebar)
return;
2003-04-03 22:37:43 +00:00
// toggle shade
m_shaded = !m_shaded;
if (m_shaded) { // i.e. should be shaded now
2003-01-05 22:14:10 +00:00
m_width_before_shade = m_window.width();
m_height_before_shade = m_window.height();
2003-02-23 21:32:37 +00:00
m_window.resize(m_window.width(), m_titlebar.height());
2003-04-03 22:37:43 +00:00
} else { // should be unshaded
2003-01-05 22:14:10 +00:00
m_window.resize(m_width_before_shade, m_height_before_shade);
2003-04-03 22:37:43 +00:00
reconfigure();
2003-01-05 22:14:10 +00:00
}
}
void FbWinFrame::move(int x, int y) {
2003-08-04 12:47:36 +00:00
// don't update unless we really changes position
if (x == window().x() && y == window().y())
return;
window().move(x, y);
// update transparent only if we need to
if (theme().alpha() == 255)
return;
redrawTitlebar();
ButtonList::iterator btn_it = m_buttons_left.begin();
ButtonList::iterator btn_it_end = m_buttons_left.begin();
for (; btn_it != btn_it_end; ++btn_it) {
(*btn_it)->clear();
2003-08-13 09:34:40 +00:00
(*btn_it)->updateTransparent();
2003-08-04 12:47:36 +00:00
}
btn_it = m_buttons_right.begin();
btn_it_end = m_buttons_right.end();
for (; btn_it != btn_it_end; ++btn_it) {
(*btn_it)->clear();
2003-08-13 09:34:40 +00:00
(*btn_it)->updateTransparent();
2003-08-04 12:47:36 +00:00
}
m_grip_left.clear();
m_grip_right.clear();
m_handle.clear();
m_grip_left.updateTransparent();
m_grip_right.updateTransparent();
m_handle.updateTransparent();
2003-01-05 22:14:10 +00:00
}
void FbWinFrame::resize(unsigned int width, unsigned int height) {
// update unshaded size if we're in shaded state and just resize width
if (m_shaded) {
m_width_before_shade = width;
m_height_before_shade = height;
m_window.resize(width, m_window.height());
} else {
m_window.resize(width, height);
}
reconfigure();
}
void FbWinFrame::resizeForClient(unsigned int width, unsigned int height) {
// total height for frame
unsigned int total_height = height;
// having a titlebar = 1 extra border + titlebar height
if (m_use_titlebar)
total_height += m_titlebar.height() + m_titlebar.borderWidth();
// having a handle = 1 extra border + handle height
if (m_use_handle)
total_height += m_handle.height() + m_handle.borderWidth();
resize(width, total_height);
2003-01-05 22:14:10 +00:00
}
void FbWinFrame::moveResize(int x, int y, unsigned int width, unsigned int height) {
move(x, y);
resize(width, height);
}
void FbWinFrame::setTitle(const std::string &titletext) {
m_titletext = titletext;
redrawTitle();
}
void FbWinFrame::setFocus(bool newvalue) {
if (m_focused == newvalue) // no need to change focus
return;
m_focused = newvalue;
reconfigure(); // reconfigure rendering for new focus value
}
void FbWinFrame::setDoubleClickTime(unsigned int time) {
m_double_click_time = time;
}
2003-01-05 22:14:10 +00:00
void FbWinFrame::setBevel(int bevel) {
m_bevel = bevel;
reconfigure();
}
void FbWinFrame::addLeftButton(FbTk::Button *btn) {
if (btn == 0) // valid button?
return;
setupButton(*btn); // setup theme and other stuff
m_buttons_left.push_back(btn);
}
void FbWinFrame::addRightButton(FbTk::Button *btn) {
if (btn == 0) // valid button?
return;
setupButton(*btn); // setup theme and other stuff
m_buttons_right.push_back(btn);
}
void FbWinFrame::removeAllButtons() {
// destroy left side
while (!m_buttons_left.empty()) {
delete m_buttons_left.back();
m_buttons_left.pop_back();
}
// destroy right side
while (!m_buttons_right.empty()) {
delete m_buttons_right.back();
m_buttons_right.pop_back();
}
2003-04-14 15:01:55 +00:00
}
2003-08-19 16:15:32 +00:00
void FbWinFrame::addLabelButton(FbTk::TextButton &btn) {
LabelList::iterator found_it = find(m_labelbuttons.begin(),
m_labelbuttons.end(),
&btn);
2003-04-14 15:01:55 +00:00
if (found_it != m_labelbuttons.end())
return;
m_labelbuttons.push_back(&btn);
}
2003-08-19 16:15:32 +00:00
void FbWinFrame::removeLabelButton(FbTk::TextButton &btn) {
LabelList::iterator erase_it = remove(m_labelbuttons.begin(),
m_labelbuttons.end(),
&btn);
2003-04-14 15:01:55 +00:00
if (erase_it == m_labelbuttons.end())
return;
m_labelbuttons.erase(erase_it);
}
2003-01-05 22:14:10 +00:00
2003-08-19 16:15:32 +00:00
void FbWinFrame::moveLabelButtonLeft(const FbTk::TextButton &btn) {
LabelList::iterator it = find(m_labelbuttons.begin(),
2003-04-16 12:27:49 +00:00
m_labelbuttons.end(),
&btn);
// make sure we found it and we're not at the begining
if (it == m_labelbuttons.end() || it == m_labelbuttons.begin())
return;
LabelList::iterator new_pos = it;
new_pos--;
2003-08-19 16:15:32 +00:00
FbTk::TextButton *item = *it;
// remove from list
m_labelbuttons.erase(it);
// insert on the new place
m_labelbuttons.insert(new_pos, item);
// update titlebar
redrawTitle();
}
2003-08-19 16:15:32 +00:00
void FbWinFrame::moveLabelButtonRight(const FbTk::TextButton &btn) {
LabelList::iterator it = find(m_labelbuttons.begin(),
m_labelbuttons.end(),
&btn);
// make sure we found it and we're not at the last item
if (it == m_labelbuttons.end() || *it == m_labelbuttons.back())
return;
2003-08-19 16:15:32 +00:00
FbTk::TextButton *item = *it;
// remove from list
LabelList::iterator new_pos = m_labelbuttons.erase(it);
new_pos++;
// insert on the new place
m_labelbuttons.insert(new_pos, item);
// update titlebar
redrawTitle();
}
2003-08-19 16:15:32 +00:00
void FbWinFrame::setLabelButtonFocus(FbTk::TextButton &btn) {
LabelList::iterator it = find(m_labelbuttons.begin(),
m_labelbuttons.end(),
&btn);
2003-04-16 12:27:49 +00:00
if (it == m_labelbuttons.end())
return;
// render label buttons
if (m_current_label != 0)
renderButtonUnfocus(*m_current_label);
2003-04-16 12:27:49 +00:00
m_current_label = *it; // current focused button
renderButtonFocus(*m_current_label);
2003-04-16 12:27:49 +00:00
}
2003-04-14 15:01:55 +00:00
void FbWinFrame::setClientWindow(FbTk::FbWindow &win) {
setClientWindow(win.window());
2003-01-05 22:14:10 +00:00
}
void FbWinFrame::setClientWindow(Window win) {
Display *display = FbTk::App::instance()->display();
XSetWindowBorderWidth(display, win, 0);
XChangeSaveSet(display, win, SetModeInsert);
XSelectInput(display, m_clientarea.window(), NoEventMask);
// we need to mask this so we don't get unmap event
XSelectInput(display, win, NoEventMask);
2003-01-05 22:14:10 +00:00
XReparentWindow(display, win, m_clientarea.window(), 0, 0);
// remask window so we get events
XSelectInput(display, win, PropertyChangeMask | StructureNotifyMask |
2003-05-15 11:17:29 +00:00
FocusChangeMask);
2003-01-05 22:14:10 +00:00
XSelectInput(display, m_clientarea.window(), SubstructureRedirectMask);
XFlush(display);
XSetWindowAttributes attrib_set;
2003-01-05 22:14:10 +00:00
attrib_set.event_mask = PropertyChangeMask | StructureNotifyMask | FocusChangeMask;
attrib_set.do_not_propagate_mask = ButtonPressMask | ButtonReleaseMask |
ButtonMotionMask;
2003-01-05 22:14:10 +00:00
XChangeWindowAttributes(display, win, CWEventMask|CWDontPropagate, &attrib_set);
m_clientarea.raise();
m_clientarea.showSubwindows();
}
void FbWinFrame::hideTitlebar() {
2003-02-20 23:21:23 +00:00
if (!m_use_titlebar)
return;
2003-01-05 22:14:10 +00:00
m_titlebar.hide();
m_use_titlebar = false;
2003-02-20 23:21:23 +00:00
m_clientarea.raise();
// only take away one borderwidth (as the other border is still the "top" border)
2003-02-22 18:31:00 +00:00
m_window.resize(m_window.width(), m_window.height() - m_titlebar.height() -
m_titlebar.borderWidth());
2003-01-05 22:14:10 +00:00
}
void FbWinFrame::showTitlebar() {
2003-02-20 23:21:23 +00:00
if (m_use_titlebar)
return;
2003-01-05 22:14:10 +00:00
m_titlebar.show();
m_use_titlebar = true;
// only add one borderwidth (as the other border is still the "top" border)
m_window.resize(m_window.width(), m_window.height() + m_titlebar.height() +
m_titlebar.borderWidth());
2003-01-05 22:14:10 +00:00
}
void FbWinFrame::hideHandle() {
if (!m_use_handle)
return;
2003-01-05 22:14:10 +00:00
m_handle.hide();
m_grip_left.hide();
m_grip_right.hide();
m_use_handle = false;
m_window.resize(m_window.width(), m_window.height() - m_handle.height() -
m_handle.borderWidth());
2003-01-05 22:14:10 +00:00
}
void FbWinFrame::showHandle() {
if (m_use_handle)
return;
2003-01-05 22:14:10 +00:00
m_handle.show();
m_grip_left.show();
m_grip_right.show();
m_use_handle = true;
m_window.resize(m_window.width(), m_window.height() + m_handle.height() +
m_handle.borderWidth());
}
void FbWinFrame::hideAllDecorations() {
hideHandle();
hideTitlebar();
// resize done by hide*
reconfigure();
}
void FbWinFrame::showAllDecorations() {
if (!m_use_handle)
showHandle();
if (!m_use_titlebar)
showTitlebar();
// resize shouldn't be necessary
2003-02-22 18:31:00 +00:00
reconfigure();
2003-01-05 22:14:10 +00:00
}
/**
Set new event handler for the frame's windows
*/
void FbWinFrame::setEventHandler(FbTk::EventHandler &evh) {
FbTk::EventManager &evm = *FbTk::EventManager::instance();
evm.add(evh, m_label);
evm.add(evh, m_titlebar);
evm.add(evh, m_handle);
evm.add(evh, m_grip_right);
evm.add(evh, m_grip_left);
evm.add(evh, m_window);
evm.add(evh, m_clientarea);
}
/**
remove event handler from windows
*/
void FbWinFrame::removeEventHandler() {
FbTk::EventManager &evm = *FbTk::EventManager::instance();
evm.remove(m_label);
evm.remove(m_titlebar);
evm.remove(m_handle);
evm.remove(m_grip_right);
evm.remove(m_grip_left);
evm.remove(m_window);
evm.remove(m_clientarea);
}
void FbWinFrame::buttonPressEvent(XButtonEvent &event) {
2003-04-14 15:01:55 +00:00
// we can ignore which window the event was generated for
LabelList::iterator btn_it = m_labelbuttons.begin();
LabelList::iterator btn_it_end = m_labelbuttons.end();
2003-04-14 15:01:55 +00:00
for (; btn_it != btn_it_end; ++btn_it) {
if ((*btn_it)->window() == event.window) {
(*btn_it)->buttonPressEvent(event);
break;
}
}
if (event.window == m_grip_right.window() ||
event.window == m_grip_left.window() ||
event.window == m_clientarea.window() ||
event.window == m_handle.window() ||
event.window == m_window.window())
return;
2003-08-04 12:47:36 +00:00
// we handle only buttons 0 to 5
if (event.button > 5 || event.button < 1)
return;
2003-01-09 18:03:33 +00:00
if (*m_commands[event.button - 1].click_pressed)
m_commands[event.button - 1].click_pressed->execute();
}
void FbWinFrame::buttonReleaseEvent(XButtonEvent &event) {
2003-04-14 15:01:55 +00:00
// we can ignore which window the event was generated for
2003-08-24 11:19:45 +00:00
LabelList::iterator button_it = find_if(m_labelbuttons.begin(),
m_labelbuttons.end(),
FbTk::Compose(bind2nd(equal_to<Window>(), event.window),
mem_fun(&FbTk::Button::window)));
if (button_it != m_labelbuttons.end())
(*button_it)->buttonReleaseEvent(event);
if (event.window == m_grip_right.window() ||
event.window == m_grip_left.window() ||
event.window == m_clientarea.window() ||
event.window == m_handle.window() ||
event.window == m_window.window())
return;
if (event.button < 1 || event.button > 5)
return;
static int last_release_time = 0;
bool double_click = (event.time - last_release_time <= m_double_click_time);
last_release_time = event.time;
int real_button = event.button - 1;
if (double_click && *m_commands[real_button].double_click)
m_commands[real_button].double_click->execute();
else if (*m_commands[real_button].click)
m_commands[real_button].click->execute();
2003-01-05 22:14:10 +00:00
}
void FbWinFrame::exposeEvent(XExposeEvent &event) {
2003-04-14 15:01:55 +00:00
if (m_label == event.window)
2003-01-05 22:14:10 +00:00
redrawTitle();
2003-08-04 12:47:36 +00:00
else if (m_handle == event.window) {
m_handle.clearArea(event.x, event.y, event.width, event.height);
m_handle.updateTransparent();
} else if (m_grip_left == event.window) {
m_grip_left.clearArea(event.x, event.y, event.width, event.height);
m_grip_left.updateTransparent();
} else if (m_grip_right == event.window) {
m_grip_right.clearArea(event.x, event.y, event.width, event.height);
m_grip_right.updateTransparent();
} else {
2003-08-24 11:19:45 +00:00
// create compare function
// that we should use with find_if
FbTk::Compose_base<std::binder2nd<std::equal_to<Window> >,
std::const_mem_fun_t<Window, FbTk::FbWindow> >
compare = FbTk::Compose(bind2nd(equal_to<Window>(), event.window),
mem_fun(&FbTk::Button::window));
LabelList::iterator btn_it = find_if(m_labelbuttons.begin(),
m_labelbuttons.end(),
compare);
if (btn_it != m_labelbuttons.end()) {
(*btn_it)->exposeEvent(event);
return;
2003-08-04 12:47:36 +00:00
}
2003-08-24 11:19:45 +00:00
ButtonList::iterator it = find_if(m_buttons_left.begin(),
m_buttons_left.end(),
compare);
if (it != m_buttons_left.end()) {
(*it)->exposeEvent(event);
return;
2003-08-04 12:47:36 +00:00
}
2003-08-24 11:19:45 +00:00
it = find_if(m_buttons_right.begin(),
m_buttons_right.end(),
compare);
2003-08-04 12:47:36 +00:00
2003-08-24 11:19:45 +00:00
if (it != m_buttons_right.end())
(*it)->exposeEvent(event);
}
2003-01-05 22:14:10 +00:00
}
void FbWinFrame::handleEvent(XEvent &event) {
2003-08-23 15:46:06 +00:00
if (event.type == ConfigureNotify && event.xconfigure.window == window().window())
2003-01-05 22:14:10 +00:00
configureNotifyEvent(event.xconfigure);
}
void FbWinFrame::configureNotifyEvent(XConfigureEvent &event) {
resize(event.width, event.height);
}
void FbWinFrame::reconfigure() {
2003-01-09 18:03:33 +00:00
2003-01-05 22:14:10 +00:00
// align titlebar and render it
if (m_use_titlebar)
reconfigureTitlebar();
2003-02-20 23:21:23 +00:00
2003-04-03 22:37:43 +00:00
// leave client+grips alone if we're shaded (it'll get fixed when we unshade)
if (!m_shaded) {
int client_top = 0;
int client_height = m_window.height();
if (m_use_titlebar) {
// only one borderwidth as titlebar is really at -borderwidth
int titlebar_height = m_titlebar.height() + m_titlebar.borderWidth();
client_top += titlebar_height;
client_height -= titlebar_height;
}
if (m_use_handle) {
client_height -= m_handle.height() + m_handle.borderWidth();
}
m_clientarea.moveResize(0, client_top,
m_window.width(), client_height);
2003-04-16 10:56:37 +00:00
if (m_use_handle) {
2003-04-03 22:37:43 +00:00
2003-04-16 10:56:37 +00:00
// align handle and grips
const int grip_height = m_handle.height();
const int grip_width = 20; //TODO
2003-04-03 22:37:43 +00:00
2003-04-16 10:56:37 +00:00
const int ypos = m_window.height() - grip_height - m_handle.borderWidth();
2003-04-03 22:37:43 +00:00
2003-04-16 10:56:37 +00:00
m_grip_left.moveResize(-m_handle.borderWidth(), ypos,
grip_width, grip_height);
2003-04-03 22:37:43 +00:00
2003-04-16 10:56:37 +00:00
m_handle.moveResize(grip_width, ypos,
m_window.width() - grip_width*2 - m_handle.borderWidth()*2,
grip_height);
2003-04-03 22:37:43 +00:00
2003-04-16 10:56:37 +00:00
m_grip_right.moveResize(m_window.width() - grip_width - m_handle.borderWidth(), ypos,
grip_width, grip_height);
}
2003-04-03 22:37:43 +00:00
}
2003-01-05 22:14:10 +00:00
2003-05-01 13:19:36 +00:00
if (!m_visible) return;
2003-01-05 22:14:10 +00:00
// render the theme
renderButtons();
2003-04-03 22:37:43 +00:00
if (!m_shaded)
renderHandles();
2003-07-10 11:36:21 +00:00
if (m_shape.get() && theme().shapePlace() == Shape::NONE || m_disable_shape)
2003-07-10 11:36:21 +00:00
m_shape.reset(0);
else if (m_shape.get() == 0 && theme().shapePlace() != Shape::NONE)
m_shape.reset(new Shape(window(), theme().shapePlace()));
else if (m_shape.get())
m_shape->setPlaces(theme().shapePlace());
if (m_shape.get())
m_shape->update();
2003-05-01 13:19:36 +00:00
// titlebar stuff rendered already by reconftitlebar
2003-01-05 22:14:10 +00:00
}
void FbWinFrame::setUseShape(bool value) {
m_disable_shape = !value;
if (m_shape.get() && m_disable_shape)
m_shape.reset(0);
else if (m_shape.get() == 0 && !m_disable_shape)
m_shape.reset(new Shape(window(), theme().shapePlace()));
}
2003-01-05 22:14:10 +00:00
unsigned int FbWinFrame::buttonHeight() const {
return m_titlebar.height() - m_bevel*2;
}
//--------------------- private area
/**
aligns and redraws title
*/
void FbWinFrame::redrawTitle() {
2003-05-01 13:19:36 +00:00
if (m_labelbuttons.size() == 0 || !m_visible)
2003-04-14 15:01:55 +00:00
return;
int button_width = label().width()/m_labelbuttons.size();
//!! TODO: bevel
2003-06-24 14:05:00 +00:00
//int border_width = m_labelbuttons.front()->window().borderWidth();
int border_width = m_labelbuttons.size() != 0 ?
2003-08-13 09:34:40 +00:00
m_labelbuttons.front()->borderWidth() : 0;
2003-04-16 10:56:37 +00:00
LabelList::iterator btn_it = m_labelbuttons.begin();
LabelList::iterator btn_it_end = m_labelbuttons.end();
2003-04-14 15:01:55 +00:00
for (unsigned int last_x = 0;
btn_it != btn_it_end;
2003-06-05 13:09:08 +00:00
++btn_it, last_x += button_width + border_width) {
2003-04-16 10:56:37 +00:00
// since we add border width pixel we should remove
// the same size for inside width so we can fit all buttons into label
2003-06-24 14:05:00 +00:00
(*btn_it)->moveResize(last_x - border_width, - border_width,
2003-04-16 10:56:37 +00:00
button_width,
label().height() + border_width);
2003-06-05 13:09:08 +00:00
(*btn_it)->clear();
2003-08-13 09:34:40 +00:00
(*btn_it)->updateTransparent();
2003-04-14 15:01:55 +00:00
}
2003-01-05 22:14:10 +00:00
}
void FbWinFrame::redrawTitlebar() {
2003-05-01 13:19:36 +00:00
if (!m_use_titlebar || !m_visible)
2003-02-20 23:21:23 +00:00
return;
2003-08-04 12:47:36 +00:00
2003-01-05 22:14:10 +00:00
redrawTitle();
2003-06-05 13:09:08 +00:00
2003-05-01 13:19:36 +00:00
}
2003-01-05 22:14:10 +00:00
/**
Align buttons with title text window
*/
void FbWinFrame::reconfigureTitlebar() {
2003-02-20 23:21:23 +00:00
if (!m_use_titlebar)
return;
2003-01-05 22:14:10 +00:00
// resize titlebar to window size with font height
2003-08-22 15:20:32 +00:00
int title_height = m_theme.font().height() == 0 ? 16 :
m_theme.font().height() + m_bevel*2 + 2;
if (m_theme.titleHeight() != 0)
title_height = m_theme.titleHeight();
2003-02-17 22:45:42 +00:00
m_titlebar.moveResize(-m_titlebar.borderWidth(), -m_titlebar.borderWidth(),
2003-08-22 15:20:32 +00:00
m_window.width(), title_height);
2003-01-05 22:14:10 +00:00
// draw left buttons first
unsigned int next_x = m_bevel;
unsigned int button_size = buttonHeight();
m_button_size = button_size;
for (size_t i=0; i < m_buttons_left.size(); i++, next_x += button_size + m_bevel) {
m_buttons_left[i]->moveResize(next_x, m_bevel,
button_size, button_size);
}
2003-04-14 15:01:55 +00:00
2003-01-05 22:14:10 +00:00
next_x += m_bevel;
// space left on titlebar between left and right buttons
unsigned int space_left = m_titlebar.width() - next_x;
if (m_buttons_right.size() != 0)
2003-02-17 22:45:42 +00:00
space_left -= m_buttons_right.size() * (button_size + m_bevel);
2003-01-05 22:14:10 +00:00
space_left -= m_bevel;
2003-08-04 12:47:36 +00:00
m_label.moveResize(next_x, m_bevel,
2003-01-05 22:14:10 +00:00
space_left, button_size);
next_x += m_label.width() + m_bevel;;
// finaly set new buttons to the right
for (size_t i=0; i < m_buttons_right.size();
++i, next_x += button_size + m_bevel) {
m_buttons_right[i]->moveResize(next_x, m_bevel,
button_size, button_size);
}
renderTitlebar();
m_titlebar.raise(); // always on top
}
void FbWinFrame::renderTitlebar() {
2003-05-01 13:19:36 +00:00
if (!m_use_titlebar || !m_visible)
2003-01-05 22:14:10 +00:00
return;
// render pixmaps
render(m_theme.titleFocusTexture(), m_title_focused_color,
m_title_focused_pm,
m_titlebar.width(), m_titlebar.height());
render(m_theme.titleUnfocusTexture(), m_title_unfocused_color,
m_title_unfocused_pm,
m_titlebar.width(), m_titlebar.height());
render(m_theme.labelFocusTexture(), m_label_focused_color,
m_label_focused_pm,
m_label.width(), m_label.height());
render(m_theme.labelUnfocusTexture(), m_label_unfocused_color,
m_label_unfocused_pm,
m_label.width(), m_label.height());
// finaly set up pixmaps for titlebar windows
2003-04-16 12:27:49 +00:00
Pixmap label_pm = None;
Pixmap title_pm = None;
FbTk::Color label_color;
FbTk::Color title_color;
getCurrentFocusPixmap(label_pm, title_pm,
label_color, title_color);
if (label_pm != 0)
m_label.setBackgroundPixmap(label_pm);
else
m_label.setBackgroundColor(label_color);
2003-04-14 15:01:55 +00:00
2003-04-16 12:27:49 +00:00
if (title_pm != 0)
m_titlebar.setBackgroundPixmap(title_pm);
else
m_titlebar.setBackgroundColor(title_color);
2003-01-05 22:14:10 +00:00
2003-04-16 12:27:49 +00:00
renderLabelButtons();
2003-05-01 13:19:36 +00:00
redrawTitlebar();
2003-01-05 22:14:10 +00:00
}
void FbWinFrame::renderHandles() {
2003-05-01 13:19:36 +00:00
if (!m_use_handle || !m_visible)
2003-01-05 22:14:10 +00:00
return;
2003-06-23 14:18:54 +00:00
2003-01-05 22:14:10 +00:00
render(m_theme.handleFocusTexture(), m_handle_focused_color,
m_handle_focused_pm,
m_handle.width(), m_handle.height());
render(m_theme.handleUnfocusTexture(), m_handle_unfocused_color,
m_handle_unfocused_pm,
m_handle.width(), m_handle.height());
if (m_focused) {
if (m_handle_focused_pm) {
m_handle.setBackgroundPixmap(m_handle_focused_pm);
} else {
m_handle.setBackgroundColor(m_handle_focused_color);
}
} else {
if (m_handle_unfocused_pm) {
m_handle.setBackgroundPixmap(m_handle_unfocused_pm);
} else {
m_handle.setBackgroundColor(m_handle_unfocused_color);
}
}
render(m_theme.gripFocusTexture(), m_grip_focused_color, m_grip_focused_pm,
m_grip_left.width(), m_grip_left.height());
render(m_theme.gripUnfocusTexture(), m_grip_unfocused_color,
m_grip_unfocused_pm,
m_grip_left.width(), m_grip_left.height());
if (m_focused) {
if (m_grip_focused_pm) {
m_grip_left.setBackgroundPixmap(m_grip_focused_pm);
m_grip_right.setBackgroundPixmap(m_grip_focused_pm);
} else {
m_grip_left.setBackgroundColor(m_grip_focused_color);
m_grip_right.setBackgroundColor(m_grip_focused_color);
}
} else {
if (m_grip_unfocused_pm) {
m_grip_left.setBackgroundPixmap(m_grip_unfocused_pm);
m_grip_right.setBackgroundPixmap(m_grip_unfocused_pm);
} else {
m_grip_left.setBackgroundColor(m_grip_unfocused_color);
m_grip_right.setBackgroundColor(m_grip_unfocused_color);
}
}
2003-08-04 12:47:36 +00:00
2003-01-05 22:14:10 +00:00
m_grip_left.clear();
2003-08-04 12:47:36 +00:00
m_grip_left.setAlpha(theme().alpha());
m_grip_left.updateTransparent();
2003-01-05 22:14:10 +00:00
m_grip_right.clear();
2003-08-04 12:47:36 +00:00
m_grip_right.setAlpha(theme().alpha());
m_grip_right.updateTransparent();
2003-01-05 22:14:10 +00:00
m_handle.clear();
2003-08-04 12:47:36 +00:00
m_handle.setAlpha(theme().alpha());
m_handle.updateTransparent();
2003-01-05 22:14:10 +00:00
}
void FbWinFrame::renderButtons() {
2003-05-01 13:19:36 +00:00
if (!m_visible) return;
2003-01-05 22:14:10 +00:00
render(m_theme.buttonFocusTexture(), m_button_color, m_button_pm,
m_button_size, m_button_size);
render(m_theme.buttonUnfocusTexture(), m_button_unfocused_color,
m_button_unfocused_pm,
m_button_size, m_button_size);
render(m_theme.buttonPressedTexture(), m_button_pressed_color,
m_button_pressed_pm,
m_button_size, m_button_size);
// setup left and right buttons
for (size_t i=0; i < m_buttons_left.size(); ++i)
setupButton(*m_buttons_left[i]);
for (size_t i=0; i < m_buttons_right.size(); ++i)
setupButton(*m_buttons_right[i]);
}
void FbWinFrame::init() {
2003-06-23 14:18:54 +00:00
m_disable_shape = false;
2003-04-16 12:27:49 +00:00
m_current_label = 0; // no focused button at first
2003-06-23 14:18:54 +00:00
// clear pixmaps
2003-01-05 22:14:10 +00:00
m_title_focused_pm = m_title_unfocused_pm = 0;
m_label_focused_pm = m_label_unfocused_pm = 0;
2003-06-23 14:18:54 +00:00
m_handle_focused_pm = m_handle_unfocused_pm = 0;
m_button_pm = m_button_unfocused_pm = m_button_pressed_pm = 0;
m_grip_unfocused_pm = m_grip_focused_pm = 0;
m_double_click_time = 200;
2003-01-05 22:14:10 +00:00
m_button_size = 26;
2003-06-23 14:18:54 +00:00
2003-04-16 22:15:22 +00:00
m_clientarea.setBorderWidth(0);
2003-01-05 22:14:10 +00:00
m_shaded = false;
m_label.show();
2003-01-09 18:03:33 +00:00
showHandle();
showTitlebar();
2003-01-09 18:03:33 +00:00
2003-06-23 14:18:54 +00:00
// Note: we don't show clientarea yet
2003-01-05 22:14:10 +00:00
setEventHandler(*this);
reconfigure();
}
/**
Setups upp background, pressed pixmap/color of the button to current theme
*/
void FbWinFrame::setupButton(FbTk::Button &btn) {
if (m_button_pressed_pm) {
btn.setPressedPixmap(m_button_pressed_pm);
}
2003-08-04 12:47:36 +00:00
//!! TODO button pressed color
2003-01-05 22:14:10 +00:00
if (m_focused) {
2003-02-23 00:57:55 +00:00
btn.setGC(m_theme.buttonPicFocusGC());
2003-01-05 22:14:10 +00:00
if (m_button_pm)
btn.setBackgroundPixmap(m_button_pm);
else
btn.setBackgroundColor(m_button_color);
} else {
2003-02-23 00:57:55 +00:00
btn.setGC(m_theme.buttonPicUnfocusGC());
2003-01-05 22:14:10 +00:00
if (m_button_unfocused_pm)
btn.setBackgroundPixmap(m_button_unfocused_pm);
else
btn.setBackgroundColor(m_button_color);
2003-08-04 12:47:36 +00:00
2003-01-05 22:14:10 +00:00
}
2003-08-04 12:47:36 +00:00
2003-08-13 09:34:40 +00:00
btn.setAlpha(theme().alpha());
2003-01-05 22:14:10 +00:00
btn.clear();
}
void FbWinFrame::render(const FbTk::Texture &tex, FbTk::Color &col, Pixmap &pm,
unsigned int w, unsigned int h) {
Pixmap tmp = pm;
if (tex.type() == (FbTk::Texture::FLAT | FbTk::Texture::SOLID)) {
pm = None;
col = tex.color();
} else
pm = m_imagectrl.renderImage(w, h, tex);
2003-06-23 14:18:54 +00:00
2003-01-05 22:14:10 +00:00
if (tmp)
m_imagectrl.removeImage(tmp);
}
2003-04-16 12:27:49 +00:00
void FbWinFrame::getCurrentFocusPixmap(Pixmap &label_pm, Pixmap &title_pm,
2003-08-13 09:34:40 +00:00
FbTk::Color &label_color, FbTk::Color &title_color) {
2003-04-16 12:27:49 +00:00
if (m_focused) {
if (m_label_focused_pm != 0)
label_pm = m_label_focused_pm;
else
label_color = m_label_focused_color;
if (m_title_focused_pm != 0)
title_pm = m_title_focused_pm;
else
title_color = m_title_focused_color;
} else {
getUnFocusPixmap(label_pm, title_pm,
label_color, title_color);
}
}
void FbWinFrame::getUnFocusPixmap(Pixmap &label_pm, Pixmap &title_pm,
2003-06-23 14:18:54 +00:00
FbTk::Color &label_color,
FbTk::Color &title_color) {
if (m_label_unfocused_pm != 0) {
2003-04-16 12:27:49 +00:00
label_pm = m_label_unfocused_pm;
2003-06-23 14:18:54 +00:00
} else
2003-04-16 12:27:49 +00:00
label_color = m_label_unfocused_color;
if (m_title_unfocused_pm != 0)
title_pm = m_title_unfocused_pm;
else
title_color = m_title_unfocused_color;
}
void FbWinFrame::renderLabelButtons() {
2003-05-01 13:19:36 +00:00
if (!m_visible) return;
2003-06-23 14:18:54 +00:00
Pixmap label_pm = 0;
Pixmap not_used_pm = 0;
2003-04-16 12:27:49 +00:00
FbTk::Color label_color;
FbTk::Color not_used_color;
getCurrentFocusPixmap(label_pm, not_used_pm,
label_color, not_used_color);
LabelList::iterator btn_it = m_labelbuttons.begin();
LabelList::iterator btn_it_end = m_labelbuttons.end();
2003-04-16 12:27:49 +00:00
for (; btn_it != btn_it_end; ++btn_it) {
if (*btn_it == m_current_label)
renderButtonFocus(**btn_it);
2003-06-05 13:09:08 +00:00
else
renderButtonUnfocus(**btn_it);
2003-04-16 12:27:49 +00:00
}
2003-06-05 13:09:08 +00:00
if (m_current_label != 0) {
if (label_pm) {
m_current_label->setBackgroundPixmap(label_pm);
} else
m_current_label->setBackgroundColor(label_color);
2003-06-23 14:18:54 +00:00
2003-06-05 13:09:08 +00:00
}
2003-04-16 12:27:49 +00:00
}
void FbWinFrame::setBorderWidth(unsigned int borderW) {
int bw_changes = 0;
// we need to change the size of the window
// if the border width changes...
if (m_use_titlebar)
bw_changes += (signed) borderW - titlebar().borderWidth();
if (m_use_handle)
bw_changes += (signed) borderW - handle().borderWidth();
window().setBorderWidth(borderW);
2003-08-25 13:15:53 +00:00
//window().setBorderColor(theme().borderColor());
titlebar().setBorderWidth(borderW);
2003-08-25 13:15:53 +00:00
//titlebar().setBorderColor(theme().borderColor());
handle().setBorderWidth(borderW);
2003-08-25 13:15:53 +00:00
//handle().setBorderColor(theme().borderColor());
gripLeft().setBorderWidth(borderW);
2003-08-25 13:15:53 +00:00
//gripLeft().setBorderColor(theme().borderColor());
gripRight().setBorderWidth(borderW);
2003-08-25 13:15:53 +00:00
//gripRight().setBorderColor(theme().borderColor());
if (bw_changes != 0)
resize(width(), height() + bw_changes);
}
2003-08-04 12:47:36 +00:00
2003-08-19 16:15:32 +00:00
void FbWinFrame::renderButtonFocus(FbTk::TextButton &button) {
button.setGC(theme().labelTextFocusGC());
button.setJustify(theme().justify());
button.setBorderWidth(1);
button.setAlpha(theme().alpha());
if (m_label_focused_pm != 0)
button.setBackgroundPixmap(m_label_focused_pm);
else
button.setBackgroundColor(m_label_focused_color);
button.clear();
}
2003-08-19 16:15:32 +00:00
void FbWinFrame::renderButtonUnfocus(FbTk::TextButton &button) {
button.setGC(theme().labelTextUnfocusGC());
button.setJustify(theme().justify());
button.setBorderWidth(1);
button.setAlpha(theme().alpha());
if (m_label_unfocused_pm != 0)
button.setBackgroundPixmap(m_label_unfocused_pm);
else
button.setBackgroundColor(m_label_unfocused_color);
button.clear();
}