From 4a3be045b28edac4953be9f195640654f8b5a1a1 Mon Sep 17 00:00:00 2001 From: Matteo Galiazzo <matteo@maltesenarrazioni.it> Date: Mon, 5 May 2008 05:05:52 -0700 Subject: add tooltips for iconbar buttons when title is too long to fit --- ChangeLog | 3 ++ src/FbTk/Button.cc | 14 ++++++- src/FbTk/Button.hh | 2 + src/FbTk/TextButton.cc | 23 +++++++++-- src/FbTk/TextButton.hh | 2 + src/IconButton.cc | 17 +++++++- src/IconButton.hh | 2 + src/Makefile.am | 1 + src/OSDWindow.hh | 2 +- src/Screen.cc | 14 +++++++ src/Screen.hh | 9 +++- src/TooltipWindow.cc | 109 +++++++++++++++++++++++++++++++++++++++++++++++++ src/TooltipWindow.hh | 53 ++++++++++++++++++++++++ 13 files changed, 241 insertions(+), 10 deletions(-) create mode 100644 src/TooltipWindow.cc create mode 100644 src/TooltipWindow.hh diff --git a/ChangeLog b/ChangeLog index 1876d6a..b243eb8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ (Format: Year/Month/Day) Changes for 1.0.1: +*08/05/05: + * Add tooltips for iconbar buttons (thanks Matteo Galiazzo) + TooltipWindow.cc/hh *08/05/02: * Minor changes for fluxbox-generate_menu (thanks skiidoo) util/fluxbox-generate_menu.in diff --git a/src/FbTk/Button.cc b/src/FbTk/Button.cc index 0284fea..9edbe5c 100644 --- a/src/FbTk/Button.cc +++ b/src/FbTk/Button.cc @@ -30,7 +30,8 @@ namespace FbTk { Button::Button(int screen_num, int x, int y, unsigned int width, unsigned int height): FbWindow(screen_num, x, y, width, height, - ExposureMask | ButtonPressMask | ButtonReleaseMask), + ExposureMask | ButtonPressMask | EnterWindowMask | + LeaveWindowMask | ButtonReleaseMask), m_background_pm(0), m_pressed_pm(0), m_pressed_color(), @@ -45,7 +46,8 @@ Button::Button(int screen_num, int x, int y, Button::Button(const FbWindow &parent, int x, int y, unsigned int width, unsigned int height): FbWindow(parent, x, y, width, height, - ExposureMask | ButtonPressMask | ButtonReleaseMask), + ExposureMask | ButtonPressMask | ButtonReleaseMask | + EnterWindowMask | LeaveWindowMask), m_background_pm(0), m_pressed_pm(0), m_pressed_color(), @@ -90,6 +92,14 @@ void Button::setBackgroundPixmap(Pixmap pm) { FbTk::FbWindow::setBackgroundPixmap(pm); } + +void Button::enterNotifyEvent(XCrossingEvent &ce){ + +} +void Button::leaveNotifyEvent(XCrossingEvent &ce){ + +} + void Button::buttonPressEvent(XButtonEvent &event) { bool update = false; if (m_pressed_pm != 0) { diff --git a/src/FbTk/Button.hh b/src/FbTk/Button.hh index 99d8ee9..1f65799 100644 --- a/src/FbTk/Button.hh +++ b/src/FbTk/Button.hh @@ -61,6 +61,8 @@ public: //@{ virtual void buttonPressEvent(XButtonEvent &event); virtual void buttonReleaseEvent(XButtonEvent &event); + virtual void enterNotifyEvent(XCrossingEvent &ce); + virtual void leaveNotifyEvent(XCrossingEvent &ce); virtual void exposeEvent(XExposeEvent &event); //@} diff --git a/src/FbTk/TextButton.cc b/src/FbTk/TextButton.cc index 561fe21..f259d89 100644 --- a/src/FbTk/TextButton.cc +++ b/src/FbTk/TextButton.cc @@ -158,11 +158,9 @@ void TextButton::drawText(int x_offset, int y_offset, FbDrawable *drawable) { translateSize(m_orientation, textw, texth); int align_x = FbTk::doAlignment(textw - x_offset - m_left_padding - m_right_padding, - bevel(), - justify(), - font(), + bevel(), justify(), font(), text().data(), text().size(), - textlen); // return new text lne + textlen); // return new text len // center text by default int center_pos = texth/2 + font().ascent()/2 - 1; @@ -183,6 +181,23 @@ void TextButton::drawText(int x_offset, int y_offset, FbDrawable *drawable) { textx, texty, m_orientation); // position } + +bool TextButton::textExceeds(int x_offset) { + + unsigned int textlen = text().size(); + // do text alignment + + unsigned int textw = width(), texth = height(); + translateSize(m_orientation, textw, texth); + + FbTk::doAlignment(textw - x_offset - m_left_padding - m_right_padding, + bevel(), justify(), font(), text().data(), text().size(), + textlen); // return new text len + + return text().size()>textlen; + +} + void TextButton::exposeEvent(XExposeEvent &event) { clearArea(event.x, event.y, event.width, event.height, false); } diff --git a/src/FbTk/TextButton.hh b/src/FbTk/TextButton.hh index eb48e61..22cda82 100644 --- a/src/FbTk/TextButton.hh +++ b/src/FbTk/TextButton.hh @@ -80,6 +80,8 @@ public: protected: virtual void drawText(int x_offset, int y_offset, FbDrawable *drawable_override); + // return true if the text will be truncated + bool textExceeds(int x_offset); private: FbTk::Font *m_font; diff --git a/src/IconButton.cc b/src/IconButton.cc index 09791c8..6b8118e 100644 --- a/src/IconButton.cc +++ b/src/IconButton.cc @@ -52,7 +52,8 @@ IconButton::IconButton(const FbTk::FbWindow &parent, FbTk::TextButton(parent, focused_theme->text().font(), win.title()), m_win(win), m_icon_window(*this, 1, 1, 1, 1, - ExposureMask | ButtonPressMask | ButtonReleaseMask), + ExposureMask |EnterWindowMask | LeaveWindowMask | + ButtonPressMask | ButtonReleaseMask), m_use_pixmap(true), m_theme(win, focused_theme, unfocused_theme), m_pm(win.screen().imageControl()) { @@ -79,6 +80,20 @@ void IconButton::exposeEvent(XExposeEvent &event) { FbTk::TextButton::exposeEvent(event); } +void IconButton::enterNotifyEvent(XCrossingEvent &ev) { + + int xoffset = 1; + if (m_icon_pixmap.drawable() != 0) + xoffset = m_icon_window.x() + m_icon_window.width() + 1; + + if (FbTk::TextButton::textExceeds(xoffset)) + m_win.screen().showTooltip(m_win.title()); +} + +void IconButton::leaveNotifyEvent(XCrossingEvent &ev) { + m_win.screen().hideTooltip(); +} + void IconButton::moveResize(int x, int y, unsigned int width, unsigned int height) { diff --git a/src/IconButton.hh b/src/IconButton.hh index b80a29b..bb41b8b 100644 --- a/src/IconButton.hh +++ b/src/IconButton.hh @@ -45,6 +45,8 @@ public: virtual ~IconButton(); void exposeEvent(XExposeEvent &event); + void enterNotifyEvent(XCrossingEvent &ce); + void leaveNotifyEvent(XCrossingEvent &ce); void clear(); void clearArea(int x, int y, unsigned int width, unsigned int height, diff --git a/src/Makefile.am b/src/Makefile.am index 0fc5a7a..337b99c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -106,6 +106,7 @@ fluxbox_SOURCES = AtomHandler.hh ArrowButton.hh ArrowButton.cc \ RootTheme.hh RootTheme.cc \ FbRootWindow.hh FbRootWindow.cc \ OSDWindow.hh OSDWindow.cc \ + TooltipWindow.hh TooltipWindow.cc \ Screen.cc Screen.hh ScreenResources.cc \ Slit.cc Slit.hh SlitTheme.hh SlitTheme.cc SlitClient.hh SlitClient.cc \ WinButton.hh WinButton.cc \ diff --git a/src/OSDWindow.hh b/src/OSDWindow.hh index 3fd5c42..e11a531 100644 --- a/src/OSDWindow.hh +++ b/src/OSDWindow.hh @@ -47,7 +47,7 @@ public: bool isVisible() const { return m_visible; } -private: +protected: void show(); BScreen &m_screen; diff --git a/src/Screen.cc b/src/Screen.cc index 7950b83..f817e6b 100644 --- a/src/Screen.cc +++ b/src/Screen.cc @@ -290,6 +290,7 @@ BScreen::ScreenResource::ScreenResource(FbTk::ResourceManager &rm, menu_delay(rm, 0, scrname + ".menuDelay", altscrname+".MenuDelay"), menu_delay_close(rm, 0, scrname + ".menuDelayClose", altscrname+".MenuDelayClose"), tab_width(rm, 64, scrname + ".tab.width", altscrname+".Tab.Width"), + tooltip_delay(rm, 500, scrname + ".tooltipDelay", altscrname+".TooltipDelay"), menu_mode(rm, FbTk::MenuTheme::DELAY_OPEN, scrname+".menuMode", altscrname+".MenuMode"), gc_line_width(rm, 1, scrname+".overlay.lineWidth", altscrname+".Overlay.LineWidth"), @@ -343,6 +344,7 @@ BScreen::BScreen(FbTk::ResourceManager &rm, m_root_window(scrn), m_geom_window(m_root_window, *this, *m_focused_windowtheme), m_pos_window(m_root_window, *this, *m_focused_windowtheme), + m_tooltip_window(m_root_window, *this, *m_focused_windowtheme), m_dummy_window(scrn, -1, -1, 1, 1, 0, true, false, CopyFromParent, InputOnly), resource(rm, screenname, altscreenname), @@ -484,6 +486,7 @@ BScreen::BScreen(FbTk::ResourceManager &rm, renderGeomWindow(); renderPosWindow(); + m_tooltip_window.setDelay(*resource.tooltip_delay); // setup workspaces and workspace menu int nr_ws = *resource.workspaces; @@ -1849,6 +1852,17 @@ void BScreen::showGeometry(int gx, int gy) { } +void BScreen::showTooltip(const std::string &text) { + if (*resource.tooltip_delay >= 0) + m_tooltip_window.showText(text); +} + +void BScreen::hideTooltip() { + if (*resource.tooltip_delay >= 0) + m_tooltip_window.hide(); +} + + void BScreen::hideGeometry() { m_geom_window.hide(); } diff --git a/src/Screen.hh b/src/Screen.hh index d42fea0..cf8bf1f 100644 --- a/src/Screen.hh +++ b/src/Screen.hh @@ -30,7 +30,7 @@ #include "RootTheme.hh" #include "WinButtonTheme.hh" #include "FbWinFrameTheme.hh" -#include "OSDWindow.hh" +#include "TooltipWindow.hh" #include "FbTk/MenuTheme.hh" #include "FbTk/EventHandler.hh" @@ -389,6 +389,9 @@ public: /// show geomentry with "width x height"-text, not size of window void showGeometry(int width, int height); void hideGeometry(); + + void showTooltip(const std::string &text); + void hideTooltip(); void setLayer(FbTk::XLayerItem &item, int layernum); // remove? no, items are never removed from their layer until they die @@ -536,6 +539,7 @@ private: FbRootWindow m_root_window; OSDWindow m_geom_window, m_pos_window; + TooltipWindow m_tooltip_window; FbTk::FbWindow m_dummy_window; struct ScreenResource { @@ -554,7 +558,8 @@ private: FbTk::Resource<FollowModel> follow_model, user_follow_model; bool ordered_dither; FbTk::Resource<int> workspaces, edge_snap_threshold, focused_alpha, - unfocused_alpha, menu_alpha, menu_delay, menu_delay_close, tab_width; + unfocused_alpha, menu_alpha, menu_delay, menu_delay_close, + tab_width, tooltip_delay; FbTk::Resource<FbTk::MenuTheme::MenuMode> menu_mode; FbTk::Resource<int> gc_line_width; diff --git a/src/TooltipWindow.cc b/src/TooltipWindow.cc new file mode 100644 index 0000000..025cc68 --- /dev/null +++ b/src/TooltipWindow.cc @@ -0,0 +1,109 @@ +// TooltipWindow.hh +// Copyright (c) 2008 Fluxbox Team (fluxgen at fluxbox dot org) +// +// 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. + + +#include "TooltipWindow.hh" +#include "Screen.hh" +#include "FbWinFrameTheme.hh" + + +TooltipWindow::TooltipWindow(const FbTk::FbWindow &parent, BScreen &screen, + FbTk::ThemeProxy<FbWinFrameTheme> &theme): + OSDWindow(parent, screen, theme), + delay(-1) { + + FbTk::RefCount<FbTk::Command<void> > raisecmd(new FbTk::SimpleCommand<TooltipWindow>(*this, &TooltipWindow::raiseTooltip)); + timer.setCommand(raisecmd); + timer.fireOnce(true); + +} + +void TooltipWindow::showText(const std::string &text) { + + lastText = text.c_str(); + if (delay == 0) + raiseTooltip(); + else + timer.start(); + +} + +void TooltipWindow::raiseTooltip() { + + if (lastText.size() == 0) + return; + + resize(lastText); + reconfigTheme(); + int h = m_theme->font().height() + m_theme->bevelWidth() * 2; + int w = m_theme->font().textWidth(lastText, lastText.size()) + m_theme->bevelWidth() * 2; + + Window root_ret; // not used + Window window_ret; // not used + int rx = 0, ry = 0; + int wx, wy; // not used + unsigned int mask; // not used + + XQueryPointer(display(), m_screen.rootWindow().window(), + &root_ret, &window_ret, &rx, &ry, &wx, &wy, &mask); + + // mouse position + int mx = rx; + int my = ry; + + // center the mouse horizontally + rx -= w/2; + int yoffset = 10; + if (ry >= yoffset + h) + ry -= yoffset + h; + else + ry += yoffset; + + // check that we are not out of screen + int outOfBound = rx + w - m_screen.width(); + if (outOfBound > 0) + rx -= outOfBound; + if (rx < 0) + rx = 0; + + moveResize(rx,ry,w, h); + + show(); + clear(); + m_theme->font().drawText(*this, m_screen.screenNumber(), + m_theme->iconbarTheme().text().textGC(), lastText, + lastText.size(), m_theme->bevelWidth(), + m_theme->bevelWidth() + m_theme->font().ascent()); +} + + +void TooltipWindow::show() { + if (m_visible) + return; + m_visible = true; + raise(); + FbTk::FbWindow::show(); +} + +void TooltipWindow::hide() { + timer.stop(); + OSDWindow::hide(); +} diff --git a/src/TooltipWindow.hh b/src/TooltipWindow.hh new file mode 100644 index 0000000..03abc1d --- /dev/null +++ b/src/TooltipWindow.hh @@ -0,0 +1,53 @@ +// TooltipWindow.hh +// Copyright (c) 2008 Fluxbox Team (fluxgen at fluxbox dot org) +// +// 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.#ifndef TOOLTIPWINDOW_HH_ +#ifndef TOOLTIPWINDOW_HH_ +#define TOOLTIPWINDOW_HH_ + +#include "OSDWindow.hh" +#include "FbTk/Command.hh" +#include "FbTk/RefCount.hh" +#include "FbTk/Timer.hh" +#include "FbTk/SimpleCommand.hh" + + +class TooltipWindow : public OSDWindow { +public: + TooltipWindow(const FbTk::FbWindow &parent, BScreen &screen, + FbTk::ThemeProxy<FbWinFrameTheme> &theme); + + void showText(const std::string &text); + void setDelay(int iDelay) { + delay = iDelay; + timer.setTimeout(delay); + } + void hide() ; + +private: + void raiseTooltip(); + void show(); + int delay; + std::string lastText; + FbTk::Timer timer; +}; + + + +#endif /*TOOLTIPWINDOW_HH_*/ -- cgit v0.11.2