diff options
Diffstat (limited to 'kicker/libkicker')
24 files changed, 5715 insertions, 0 deletions
diff --git a/kicker/libkicker/CMakeLists.txt b/kicker/libkicker/CMakeLists.txt new file mode 100644 index 000000000..e2ec5a6ba --- /dev/null +++ b/kicker/libkicker/CMakeLists.txt @@ -0,0 +1,42 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +################################################# + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + +link_directories( + ${TQT_LIBRARY_DIRS} +) + + +##### other data ################################ + +install( FILES kickerSettings.kcfg DESTINATION ${KCFG_INSTALL_DIR} ) + + +##### kickermain (shared) ####################### + +set( target kickermain ) + +set( ${target}_SRCS + appletinfo.cpp global.cpp kickertip.cpp menuinfo.cpp + panelbutton.cpp panner.cpp kickerSettings.kcfgc + kshadowsettings.cpp kshadowengine.cpp paneldrag.cpp + simplebutton.cpp +) + +tde_add_library( ${target} SHARED AUTOMOC + SOURCES ${${target}_SRCS} + VERSION 1.0.0 + LINK tdeio-shared + DESTINATION ${LIB_INSTALL_DIR} +) diff --git a/kicker/libkicker/Makefile.am b/kicker/libkicker/Makefile.am new file mode 100644 index 000000000..fb917c67e --- /dev/null +++ b/kicker/libkicker/Makefile.am @@ -0,0 +1,19 @@ +INCLUDES = $(all_includes) + +lib_LTLIBRARIES = libkickermain.la + +libkickermain_la_SOURCES = appletinfo.cpp global.cpp kickertip.cpp \ + menuinfo.cpp panelbutton.cpp panner.cpp \ + kickerSettings.kcfgc kshadowsettings.cpp \ + kshadowengine.cpp paneldrag.cpp \ + simplebutton.cpp + +libkickermain_la_METASOURCES = AUTO + +libkickermain_la_LDFLAGS = $(all_libraries) -version-info 1:0:0 -no-undefined +libkickermain_la_LIBADD = $(LIB_TDEIO) + +kde_kcfg_DATA = kickerSettings.kcfg + +messages: rc.cpp + $(XGETTEXT) *.cpp *.h -o $(podir)/libkicker.pot diff --git a/kicker/libkicker/appletinfo.cpp b/kicker/libkicker/appletinfo.cpp new file mode 100644 index 000000000..4a851df55 --- /dev/null +++ b/kicker/libkicker/appletinfo.cpp @@ -0,0 +1,112 @@ +/***************************************************************** + +Copyright (c) 1996-2000 the kicker authors. See file AUTHORS. + +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 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 <tqfileinfo.h> +#include <kdesktopfile.h> +#include <tdeapplication.h> + +#include "appletinfo.h" + +AppletInfo::AppletInfo( const TQString& deskFile, const TQString& configFile, const AppletInfo::AppletType type) + : m_type (type), + m_unique(true), + m_hidden(false) +{ + TQFileInfo fi(deskFile); + m_desktopFile = fi.fileName(); + + const char* resource = "applets"; + switch (type) + { + case Extension: + resource = "extensions"; + break; + case BuiltinButton: + resource = "builtinbuttons"; + break; + case SpecialButton: + resource = "specialbuttons"; + break; + case Undefined: + case Applet: + default: + break; + } + + KDesktopFile df(m_desktopFile, true, resource); + + // set the appletssimple attributes + setName(df.readName()); + setComment(df.readComment()); + setIcon(df.readIcon()); + + // library + setLibrary(df.readEntry("X-TDE-Library")); + + // is it a unique applet? + setIsUnique(df.readBoolEntry("X-TDE-UniqueApplet", false)); + + // should it be shown in the gui? + m_hidden = df.readBoolEntry("Hidden", false); + + if (configFile.isEmpty()) + { + // generate a config file base name from the library name + m_configFile = m_lib.lower(); + + if (m_unique) + { + m_configFile.append("rc"); + } + else + { + m_configFile.append("_") + .append(kapp->randomString(20).lower()) + .append("_rc"); + } + } + else + { + m_configFile = configFile; + } +} + +bool AppletInfo::operator!=( const AppletInfo& rhs) const +{ + return configFile() != rhs.configFile(); +} + +bool AppletInfo::operator<( const AppletInfo& rhs ) const +{ + return ( TQString::localeAwareCompare( name(), rhs.name() ) < 0 ); +} + +bool AppletInfo::operator> ( const AppletInfo& rhs ) const +{ + return ( TQString::localeAwareCompare( name(), rhs.name() ) > 0 ); +} + +bool AppletInfo::operator<= ( const AppletInfo& rhs ) const +{ + return ( TQString::localeAwareCompare( name(), rhs.name() ) <= 0 ); +} diff --git a/kicker/libkicker/appletinfo.h b/kicker/libkicker/appletinfo.h new file mode 100644 index 000000000..f89bb6aea --- /dev/null +++ b/kicker/libkicker/appletinfo.h @@ -0,0 +1,92 @@ +/***************************************************************** + +Copyright (c) 1996-2000 the kicker authors. See file AUTHORS. + +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 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 __appletinfo_h__ +#define __appletinfo_h__ + +#include <tqmap.h> +#include <tqptrlist.h> +#include <tqstring.h> +#include <tqvaluevector.h> + +#include <kdemacros.h> + +class KDE_EXPORT AppletInfo +{ + public: + typedef TQValueVector<AppletInfo> List; + typedef TQMap<TQObject*, AppletInfo*> Dict; + + enum AppletType { Undefined = 0, + Applet = 1, + BuiltinButton = 2, + SpecialButton = 4, + Extension = 8, + Button = BuiltinButton | SpecialButton }; + + AppletInfo(const TQString& desktopFile = TQString::null, + const TQString& configFile = TQString::null, + const AppletType type = Undefined); + + TQString name() const { return m_name; } + TQString comment() const { return m_comment; } + TQString icon() const { return m_icon; } + + AppletType type() const { return m_type; } + + TQString library() const { return m_lib; } + TQString desktopFile() const { return m_desktopFile; } + TQString configFile() const { return m_configFile; } + + bool isUniqueApplet() const { return m_unique; } + bool isHidden() const { return m_hidden; } + + void setConfigFile(TQString cf) { m_configFile = cf; } + + bool operator<(const AppletInfo& rhs) const; + bool operator>(const AppletInfo& rhs) const; + bool operator<=(const AppletInfo& rhs) const; + bool operator!=(const AppletInfo& rhs) const; + + void setType(AppletType type) { m_type = type; } + + protected: + void setName(TQString name) { m_name = name; } + void setComment(TQString comment) { m_comment = comment; } + void setIcon(TQString icon) { m_icon = icon; } + void setLibrary(TQString lib) { m_lib = lib; } + void setIsUnique(bool u) { m_unique = u; } + + private: + TQString m_name; + TQString m_comment; + TQString m_icon; + TQString m_lib; + TQString m_desktopFile; + TQString m_configFile; + AppletType m_type; + bool m_unique; + bool m_hidden; +}; + +#endif diff --git a/kicker/libkicker/global.cpp b/kicker/libkicker/global.cpp new file mode 100644 index 000000000..62f7f055a --- /dev/null +++ b/kicker/libkicker/global.cpp @@ -0,0 +1,490 @@ +/***************************************************************** + +Copyright (c) 1996-2000 the kicker authors. See file AUTHORS. + +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 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 <tqapplication.h> +#include <tqbitmap.h> +#include <tqfile.h> +#include <tqpopupmenu.h> +#include <tqregexp.h> +#include <tqpainter.h> + +#include <kiconeffect.h> +#include <kiconloader.h> +#include <tdeio/netaccess.h> +#include <kstandarddirs.h> +#include <kservice.h> +#include <ksimpleconfig.h> + +#include "global.h" +#include "kickerSettings.h" + +namespace KickerLib +{ + +KPanelExtension::Position directionToPosition(KPanelApplet::Direction d ) +{ + switch (d) + { + case KPanelApplet::Down: + return KPanelExtension::Top; + break; + + case KPanelApplet::Left: + return KPanelExtension::Right; + break; + + case KPanelApplet::Right: + return KPanelExtension::Left; + break; + + case KPanelApplet::Up: + default: + return KPanelExtension::Bottom; + break; + } +} + +KPanelExtension::Position directionToPopupPosition(KPanelApplet::Direction d) +{ + switch (d) + { + case KPanelApplet::Up: + return KPanelExtension::Top; + break; + + case KPanelApplet::Down: + return KPanelExtension::Bottom; + break; + + case KPanelApplet::Left: + return KPanelExtension::Left; + break; + + case KPanelApplet::Right: + default: + return KPanelExtension::Right; + break; + } +} + +KPanelApplet::Direction positionToDirection(KPanelExtension::Position p) +{ + switch (p) + { + case KPanelExtension::Top: + return KPanelApplet::Down; + break; + + case KPanelExtension::Right: + return KPanelApplet::Left; + break; + + case KPanelExtension::Left: + return KPanelApplet::Right; + break; + + case KPanelExtension::Bottom: + default: + return KPanelApplet::Up; + break; + } +} + +KPanelApplet::Direction arrowToDirection(TQt::ArrowType p) +{ + switch (p) + { + case Qt::DownArrow: + return KPanelApplet::Down; + break; + + case Qt::LeftArrow: + return KPanelApplet::Left; + break; + + case Qt::RightArrow: + return KPanelApplet::Right; + break; + + case Qt::UpArrow: + default: + return KPanelApplet::Up; + break; + } +} + +int sizeValue(KPanelExtension::Size s) +{ + switch (s) + { + case KPanelExtension::SizeTiny: + return 24; + break; + + case KPanelExtension::SizeSmall: + return 30; + break; + + case KPanelExtension::SizeNormal: + return 46; + break; + + case KPanelExtension::SizeLarge: + default: + return 58; + break; + } +} + +int maxButtonDim() +{ + int maxDim; + //return (2 * KickerSettings::iconMargin()) + TDEIcon::SizeLarge; + + KSimpleConfig *kickerconfig = new KSimpleConfig( TQString::fromLatin1( "kickerrc" )); + kickerconfig->setGroup("General"); + maxDim = (2 * KickerSettings::iconMargin()) + kickerconfig->readNumEntry("panelIconWidth", TDEIcon::SizeLarge);; + delete kickerconfig; + return maxDim; +} + +TQString newDesktopFile(const KURL& url) +{ + TQString base = url.fileName(); + if (base.endsWith(".desktop")) + base.truncate(base.length()-8); + TQRegExp r("(.*)(?=-\\d+)"); + if (r.search(base) > -1) + base = r.cap(1); + + TQString file = base + ".desktop"; + + for(int n = 1; ++n; ) + { + TQString path = locate("appdata", file); + if (path.isEmpty()) + break; + + file = TQString("%2-%1.desktop").arg(n).arg(base); + } + file = locateLocal("appdata", file); + return file; +} + +TQString copyDesktopFile(const KURL& url) +{ + TQString file = newDesktopFile(url); + KURL dest; + dest.setPath(file); + TDEIO::NetAccess::upload(url.path(), dest, 0); + return file; +} + +TQPopupMenu* reduceMenu(TQPopupMenu *menu) +{ + if (menu->count() != 1) + { + return menu; + } + + TQMenuItem *item = menu->findItem(menu->idAt(0)); + + if (item->popup()) + { + return reduceMenu(item->popup()); + } + + return menu; +} + +TQPoint popupPosition(KPanelApplet::Direction d, + const TQWidget* popup, + const TQWidget* source, + const TQPoint& offset) +{ + TQRect r; + if (source->isTopLevel()) + { + r = source->geometry(); + } + else + { + r = TQRect(source->mapToGlobal(TQPoint(0, 0)), + source->mapToGlobal(TQPoint(source->width(), source->height()))); + + switch (d) + { + case KPanelApplet::Left: + case KPanelApplet::Right: + r.setLeft( source->topLevelWidget()->x() ); + r.setWidth( source->topLevelWidget()->width() ); + break; + case KPanelApplet::Up: + case KPanelApplet::Down: + r.setTop( source->topLevelWidget()->y() ); + r.setHeight( source->topLevelWidget()->height() ); + break; + } + } + + switch (d) + { + case KPanelApplet::Left: + case KPanelApplet::Right: + { + TQDesktopWidget* desktop = TQApplication::desktop(); + TQRect screen = desktop->screenGeometry(desktop->screenNumber(const_cast<TQWidget*>(source))); + int x = (d == KPanelApplet::Left) ? r.left() - popup->width() : + r.right() + 1; + int y = r.top() + offset.y(); + + // try to keep this on screen + if (y + popup->height() > screen.bottom()) + { + y = r.bottom() - popup->height() + offset.y(); + + if (y < screen.top()) + { + y = screen.bottom() - popup->height(); + + if (y < screen.top()) + { + y = screen.top(); + } + } + } + + return TQPoint(x, y); + } + case KPanelApplet::Up: + case KPanelApplet::Down: + default: + { + int x = 0; + int y = (d == KPanelApplet::Up) ? r.top() - popup->height() : + r.bottom() + 1; + + if (TQApplication::reverseLayout()) + { + x = r.right() - popup->width() + 1; + + if (offset.x() > 0) + { + x -= r.width() - offset.x(); + } + + // try to keep this on the screen + if (x - popup->width() < 0) + { + x = r.left(); + } + + return TQPoint(x, y); + } + else + { + TQDesktopWidget* desktop = TQApplication::desktop(); + TQRect screen = desktop->screenGeometry(desktop->screenNumber(const_cast<TQWidget*>(source))); + x = r.left() + offset.x(); + + // try to keep this on the screen + if (x + popup->width() > screen.right()) + { + x = r.right() - popup->width() + 1 + offset.x(); + + if (x < screen.left()) + { + x = screen.left(); + } + } + } + + return TQPoint(x, y); + } + } +} + +void colorize(TQImage& image) +{ + TDEConfig *config = TDEGlobal::config(); + config->setGroup("WM"); + TQColor color = TQApplication::palette().active().highlight(); + TQColor activeTitle = config->readColorEntry("activeBackground", &color); + TQColor inactiveTitle = config->readColorEntry("inactiveBackground", &color); + + // figure out which color is most suitable for recoloring to + int h1, s1, v1, h2, s2, v2, h3, s3, v3; + activeTitle.hsv(&h1, &s1, &v1); + inactiveTitle.hsv(&h2, &s2, &v2); + TQApplication::palette().active().background().hsv(&h3, &s3, &v3); + + if ( (kAbs(h1-h3)+kAbs(s1-s3)+kAbs(v1-v3) < kAbs(h2-h3)+kAbs(s2-s3)+kAbs(v2-v3)) && + ((kAbs(h1-h3)+kAbs(s1-s3)+kAbs(v1-v3) < 32) || (s1 < 32)) && (s2 > s1)) + color = inactiveTitle; + else + color = activeTitle; + + // limit max/min brightness + int r, g, b; + color.rgb(&r, &g, &b); + int gray = tqGray(r, g, b); + if (gray > 180) { + r = (r - (gray - 180) < 0 ? 0 : r - (gray - 180)); + g = (g - (gray - 180) < 0 ? 0 : g - (gray - 180)); + b = (b - (gray - 180) < 0 ? 0 : b - (gray - 180)); + } else if (gray < 76) { + r = (r + (76 - gray) > 255 ? 255 : r + (76 - gray)); + g = (g + (76 - gray) > 255 ? 255 : g + (76 - gray)); + b = (b + (76 - gray) > 255 ? 255 : b + (76 - gray)); + } + color.setRgb(r, g, b); + TDEIconEffect::colorize(image, color, 1.0); +} + +TQColor blendColors(const TQColor& c1, const TQColor& c2) +{ + int r1, g1, b1; + int r2, g2, b2; + + c1.rgb(&r1, &g1, &b1); + c2.rgb(&r2, &g2, &b2); + + r1 += (int) (.5 * (r2 - r1)); + g1 += (int) (.5 * (g2 - g1)); + b1 += (int) (.5 * (b2 - b1)); + + return TQColor(r1, g1, b1); +} + +TQColor shadowColor(const TQColor& c) +{ + int r = c.red(); + int g = c.green(); + int b = c.blue(); + + if ( r < 128 ) + r = 255; + else + r = 0; + + if ( g < 128 ) + g = 255; + else + g = 0; + + if ( b < 128 ) + b = 255; + else + b = 0; + + return TQColor( r, g, b ); +} + +TQIconSet menuIconSet(const TQString& icon) +{ + TQIconSet iconset; + int iconSize = KickerSettings::menuEntryHeight(); + + if (iconSize < 0) + { + return iconset; + } + + if (icon != "unknown") + { + if (iconSize > 0) + { + iconset = TDEGlobal::iconLoader()->loadIconSet(icon, + TDEIcon::NoGroup, + iconSize, true); + } + else if (iconSize == 0) + { + TQPixmap normal = TDEGlobal::iconLoader()->loadIcon(icon, + TDEIcon::Small, + 0, + TDEIcon::DefaultState, + 0, + true); + + TQPixmap active = TDEGlobal::iconLoader()->loadIcon(icon, + TDEIcon::Small, + 0, + TDEIcon::ActiveState, + 0, + true); + + // make sure they are not larger than 20x20 + if (normal.width() > 20 || normal.height() > 20) + { + normal.convertFromImage(TQImage(normal.convertToImage()).smoothScale(20,20)); + } + + if (active.width() > 20 || active.height() > 20) + { + active.convertFromImage(TQImage(active.convertToImage()).smoothScale(20,20)); + } + + iconset.setPixmap(normal, TQIconSet::Small, TQIconSet::Normal); + iconset.setPixmap(active, TQIconSet::Small, TQIconSet::Active); + } + } + + if (iconset.isNull()) + { + TQPixmap pix(iconSize, iconSize); + TQBitmap map(iconSize, iconSize, true); + pix.setMask(map); + iconset = TQIconSet(pix, pix); + } + + return iconset; +} + +void drawBlendedRect(TQPainter *p, const TQRect &r, const TQColor &color, int alpha) +{ + static TQPixmap pix; + static TQColor last_color = Qt::black; + static int last_alpha = 0; + + if (pix.isNull() || last_color != color || last_alpha != alpha) + { + TQImage img(16, 16, 32); +#ifdef USE_QT4 + img.setAlphaBuffer(true); + img.fill(((uint)(alpha & 0xFF) << 24) | (color.rgb() & 0xFFFFFF)); +#else // USE_QT4 + img.setAlphaBuffer(false); + img.fill(((uint)(alpha & 0xFF) << 24) | (color.rgb() & 0xFFFFFF)); + img.setAlphaBuffer(true); +#endif // USE_QT4 + pix.convertFromImage(img); + last_color = color; + last_alpha = alpha; + } + + p->drawTiledPixmap(r, pix); +} + +} // namespace + diff --git a/kicker/libkicker/global.h b/kicker/libkicker/global.h new file mode 100644 index 000000000..663987174 --- /dev/null +++ b/kicker/libkicker/global.h @@ -0,0 +1,112 @@ +/***************************************************************** + +Copyright (c) 1996-2000 the kicker authors. See file AUTHORS. + +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 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 __pglobal_h__ +#define __pglobal_h__ + +#include <tqiconset.h> +#include <tqmap.h> + +#include <kpanelapplet.h> +#include <kpanelextension.h> +#include <kurl.h> + +namespace KickerLib +{ + +/* + * Functions to convert between various enums + */ +KDE_EXPORT KPanelExtension::Position directionToPosition(KPanelApplet::Direction d); +KDE_EXPORT KPanelExtension::Position directionToPopupPosition(KPanelApplet::Direction d); +KDE_EXPORT KPanelApplet::Direction positionToDirection(KPanelExtension::Position p); +KDE_EXPORT KPanelApplet::Direction arrowToDirection(TQt::ArrowType p); +KDE_EXPORT int sizeValue(KPanelExtension::Size s); + +/** + * Pixel sizes for but sizes and margins + */ +KDE_EXPORT int maxButtonDim(); + +/** + * Tint the image to reflect the current color scheme + * Used, for instance, by KMenu side bar + */ +KDE_EXPORT void colorize(TQImage& image); + +/** + * Blend a color rectangle on a painter + */ +KDE_EXPORT void drawBlendedRect(TQPainter *p, const TQRect &r, const TQColor &color = Qt::black, int alpha = 0x40); + +/** + * Blend two colours together to get a colour halfway in between + */ +KDE_EXPORT TQColor blendColors(const TQColor& c1, const TQColor& c2); + +/** + * Create or copy .desktop files for use in kicker safely and easily + */ +KDE_EXPORT TQString copyDesktopFile(const KURL&url); +KDE_EXPORT TQString newDesktopFile(const KURL&url); + + +/** + * Reduces a popup menu + * + * When a popup menu contains only 1 sub-menu, it makes no sense to + * show this popup-menu but we better show the sub-menu directly. + * + * This function checks whether that is the case and returns either the + * original menu or the sub-menu when appropriate. + */ +KDE_EXPORT TQPopupMenu *reduceMenu(TQPopupMenu *); + + +/** + * Calculate the appropriate position for a popup menu based on the + * direction, the size of the menu, the widget geometry, and a optional + * point in the local coordinates of the widget. + */ +KDE_EXPORT TQPoint popupPosition(KPanelApplet::Direction d, + const TQWidget* popup, + const TQWidget* source, + const TQPoint& offset = TQPoint(0, 0)); + +/** + * Calculate an acceptable inverse of the given color wich will be used + * as the shadow color. + */ +KDE_EXPORT TQColor shadowColor(const TQColor& c); + +/** + * Get an appropriate for a menu in Plasma. As the user may set this size + * globally, it is important to always use this method. + * @param icon the name of icon requested + * @return the icon set for the requested icon + */ +KDE_EXPORT TQIconSet menuIconSet(const TQString& icon); + +} + +#endif // __pglobal_h__ diff --git a/kicker/libkicker/kickerSettings.kcfg b/kicker/libkicker/kickerSettings.kcfg new file mode 100644 index 000000000..0abc51bf0 --- /dev/null +++ b/kicker/libkicker/kickerSettings.kcfg @@ -0,0 +1,509 @@ +<?xml version="1.0" encoding="UTF-8"?> +<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0 + http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" > + +<include>tdeapplication.h</include> +<include>tdelocale.h</include> +<kcfgfile arg="true" /> + +<group name="General"> + +<entry name="Locked" type="Bool" > + <label>When this option is enabled, the panels may not be moved and items cannot be removed or added</label> + <default>false</default> + </entry> + +<entry name="ConserveSpace" type="Bool" > + <label>Enable conserve space</label> + <default>true</default> + </entry> + +<entry name="Transparent" type="Bool" > + <label>Enable transparency</label> + <whatsthis>When this option is enabled, the panel will become pseudo-transparent</whatsthis> + <default>false</default> + </entry> + +<entry name="UseResizeHandle" type="Bool" > + <label>Enable resize handles</label> + <whatsthis>When this option is enabled, the panel will provide a resize handle on order to change its width via click-and-drag</whatsthis> + <default>false</default> + </entry> + +<entry name="ShowDeepButtons" type="Bool" > + <label>Make the task buttons push further into the screen when activated</label> + <default>false</default> + </entry> + +<entry name="MenubarPanelTransparent" type="Bool" > + <label>Enable transparency for menubar panel</label> + <whatsthis>When this option is enabled, the panel containing the menubar will become pseudo-transparent as well</whatsthis> + <default>false</default> + </entry> + +<entry name="MenubarPanelBlurred" type="Bool" > + <label>Enable blurring for menubar panel</label> + <whatsthis>When this option is enabled, the panel containing the menubar will blur pseudo-transparent image</whatsthis> + <default>false</default> + </entry> + +<entry name="UseBackgroundTheme" type="Bool" > + <label>Enable background image</label> + <whatsthis>When this option is enabled, the panel will display a tiled image as its background</whatsthis> + <default>true</default> + </entry> + +<entry name="ColorizeBackground" type="Bool" > + <label>Enable colourized background.</label> + <default>false</default> + </entry> + +<entry name="RotateBackground" type="Bool" > + <label>Rotate background</label> + <whatsthis>When this option is enabled, when the panel is placed on the side or top edges of the screen, the background image will be rotated to match the panel's orientation</whatsthis> + <default>true</default> + </entry> + +<entry name="BackgroundTheme" type="Path" > + <label>Background image</label> + <whatsthis>Here you can choose an image to be displayed on the panel. Press the 'browse' button to choose a theme using the file dialog. This option is only effective if 'Enable background image' is selected</whatsthis> + <default>wallpapers/default.png</default> + </entry> + +<entry name="TintValue" type="Int" > + <label>Controls the saturation level of the tint color used with transparent panels</label> + <default>33</default> + <min>0</min> + <max>100</max> + </entry> + +<entry name="TintColor" type="Color" > + <label>The tint color used to colorize transparent panels</label> + <default code="true">(TQApplication::palette().active().mid())</default> + <whatsthis>This option sets the color to use when tinting transparent panels</whatsthis> + </entry> + +<entry name="UnhideLocation" type="Int"> + <label>Raise when the pointer touches the screen here</label> + <default>0</default> + </entry> + +<entry name="FadeOutAppletHandles" type="Bool"> + <label>Fade out applet handles</label> + <default>true</default> + <whatsthis>Select this option to make applet handles only visible on mouse hover. Applet handles let you move, remove and configure applets.</whatsthis> + </entry> + +<entry name="HideAppletHandles" type="Bool"> + <label>Hide applet handles</label> + <default>false</default> + <whatsthis>Select this option to always hide the applet handles. Beware this could disable moving, removing or configuring some applets.</whatsthis> + </entry> + +<entry name="ShowToolTips" type="Bool" > + <label>Show informational tooltips</label> + <default>true</default> + </entry> + +<entry name="ShowIconActivationEffect" type="Bool" > + <label>Show visual effect when panel icon is activated.</label> + <default>true</default> + </entry> + +<entry name="UntrustedApplets" type="StringList"> + <label>A list of applets that have been loaded at runtime. In the case of a crash these applets will not be loaded at the next Kicker start, in case they caused the crash</label> + </entry> + +<entry name="UntrustedExtensions" type="StringList"> + <label>A list of extensions that have been loaded at runtime. In the case of a crash these extensions will not be loaded at the next Kicker start, in case they caused the crash</label> + </entry> + +<entry name="LegacyKMenu" type="Bool" > + <label>When this option is enabled, the classic TDE Menu is used.</label> + <default>true</default> + </entry> + +<entry name="OpenOnHover" type="Bool" > + <label>When this option is enabled, the Kickoff Menu opens on mouse hover.</label> + <default>true</default> + </entry> + +<entry name="ScrollFlipView" type="Bool" > + <label>When this option is enabled, the Kickoff Menu application view switching will scroll.</label> + <default>true</default> + </entry> + +<entry name="KMenuWidth" type="Int"> + <label>Preferred width of the KMenu</label> + <default>0</default> + </entry> + +<entry name="KMenuHeight" type="Int"> + <label>Preferred width of the KMenu</label> + <default>0</default> + </entry> + +<entry name="KickoffFontPointSizeOffset" type="Int" > + <label>With this option the scale of the fonts Kickoff uses can be influenced</label> + <default>0</default> + <min>-100</min> + <max>100</max> + </entry> + +<entry name="KickoffSearchAddressBook" type="Bool" > + <label>When this option is enabled, tdeabc is utilized to search for addresses. This may start KMail.</label> + <default>false</default> + </entry> + +<entry name="KickoffDrawGeekoEye" type="Bool" > + <label>When this option is enabled, the Geeko eye moves when the mouse hovers the start menu button</label> + <default>false</default> + </entry> + +<entry name="KickoffTabBarFormat" type="Enum" > + <choices> + <choice name="LabelAndIcon"> + <label>Show names and icons on tabs</label> + </choice> + <choice name="LabelOnly"> + <label>Show only the names</label> + </choice> + <choice name="IconOnly"> + <label>Show only the icons</label> + </choice> + </choices> + <default>LabelAndIcon</default> + <label>Appearace of the Kickoff tabbar</label> + </entry> + +<entry name="KickoffSwitchTabsOnHover" type="Bool" > + <label>When this option is enabled, the tabs in the Kickoff menu will switch without the need to click</label> + <default>true</default> + </entry> + + +</group> + +<group name="menus"> + + <entry name="MenuEntryFormat" type="Enum" > + <choices> + <choice name="NameOnly"> + <label>Show simple menu entries</label> + </choice> + <choice name="NameAndDescription"> + <label>Show names first on detailed entries</label> + </choice> + <choice name="DescriptionOnly"> + <label>Show only description for menu entries</label> + </choice> + <choice name="DescriptionAndName"> + <label>Show detailed menu entries</label> + </choice> + </choices> + <default>DescriptionAndName</default> + <label>Formation of the menu entry text</label> + </entry> + +<entry name="ShowMenuTitles" type="Bool" > + <label>Show section titles in Kmenu</label> + <default>true</default> + </entry> + +<entry name="ReduceMenuDepth" type="Bool" > + <label>Simplify menus with only a single item inside</label> + <default>false</default> + </entry> + +<entry name="MenuEntryHeight" type="Int" > + <label>Height of menu entries in pixels</label> + <default>0</default> + </entry> + +<entry name="ShowHiddenFiles" type="Bool" > + <label>Show hidden files in Quick Browser</label> + <default>false</default> + </entry> + +<entry name="MaxEntries2" type="UInt" > + <label>Maximum number of entries</label> + <default>30</default> + <min>1</min> + </entry> + +<entry name="UseBookmarks" type="Bool" > + <label>Show bookmarks in KMenu</label> + <default>false</default> + </entry> + +<entry name="UseBrowser" type="Bool" > + <label>Use the Quick Browser</label> + <default>false</default> + </entry> + +<entry name="MenuExtensions" key="Extensions" type="StringList" > + <label>Optional Menus</label> + <default>prefmenu.desktop,systemmenu.desktop</default> + </entry> + +<entry name="RecentAppsStat" type="StringList" > + <label>Recently used applications</label> + </entry> + +<entry name="NumVisibleEntries" type="UInt" > + <label>Number of visible entries</label> + <default>5</default> + <max>100</max> + </entry> + +<entry name="RecentVsOften" type="Bool" > + <label>Show most recently used applications rather than most frequently used</label> + <default>false</default> + </entry> + +<entry name="Favorites" type="StringList"> + <label>The menu entries shown in the Favorites tab</label> + </entry> + +<entry name="FirstRun" type="Bool" > + <label>Whether the panel has been started before or not</label> + <default>false</default> + </entry> + +<entry name="FirstSeenApps" type="StringList"> + <label>When the applications were first seen by Kickoff</label> + </entry> + +</group> + +<group name="button_tiles"> + +<entry name="EnableKMenuTiles" type="Bool"> + <label>Enable a tile background image for the KMenu button</label> + <default>false</default> + </entry> + +<entry name="EnableDesktopButtonTiles" type="Bool"> + <label>Enable a tile background image for the Desktop button</label> + <default>false</default> + </entry> + +<entry name="EnableURLTiles" type="Bool" > + <label>Enable a tile background image for Application, URL and special buttons</label> + <default>false</default> + </entry> + +<entry name="EnableBrowserTiles" type="Bool" > + <label>Enable a tile background image for the Quick Browser button</label> + <default>false</default> + </entry> + +<entry name="EnableWindowListTiles" type="Bool" > + <label>Enable a tile background image for the Window List button</label> + <default>false</default> + </entry> + +<entry name="KMenuTile" type="Path" > + <label>Image tile for Kmenu button background</label> + </entry> + +<entry name="KMenuTileColor" type="Color" > + <label>Color to use for Kmenu button background</label> + <default code="true">QColor()</default> + </entry> + +<entry name="DesktopButtonTile" type="Path" > + <label>Image tile for Desktop button background</label> + </entry> + +<entry name="DesktopButtonTileColor" type="Color" > + <label>Color to use for Kmenu button background</label> + <default code="true">QColor()</default> + </entry> + +<entry name="URLTile" type="Path" > + <label>Image tile for Application, URL and special button backgrounds</label> + </entry> + +<entry name="URLTileColor" type="Color" > + <label>Color to use for Application, URL and special button backgrounds</label> + <default code="true">QColor()</default> + </entry> + +<entry name="BrowserTile" type="Path" > + <label>Image tile for Browser button background</label> + </entry> + +<entry name="BrowserTileColor" type="Color" > + <label>Color to use for Browser button background</label> + <default code="true">QColor()</default> + </entry> + +<entry name="WindowListTile" type="Path" > + <label>Image tile for Window List button background</label> + </entry> + +<entry name="WindowListTileColor" type="Color" > + <label>Color to use for Window List button background</label> + <default code="true">QColor()</default> + </entry> + +</group> + +<group name="KMenu" > + + <entry name="UseSidePixmap" type="Bool" > + <label>Use side image in Kmenu</label> + <default>true</default> + </entry> + + <entry name="UseTooltip" type="Bool" > + <label>Use Tooltip in Kmenu</label> + <default>false</default> + </entry> + + <entry name="UseSearchBar" type="Bool" > + <label>Show searh field in Kmenu</label> + <default>true</default> + </entry> + + <entry name="UseTopSide" type="Bool" > + <label>Use side image on top of Kmenu</label> + <default>false</default> + </entry> + + <entry name="LeftSideTopPixmapName" key="LeftSideTopName" type="String" > + <label>The name of the file to use as the side image in the TDE Menu</label> + <default>kside_top_left.png</default> + </entry> + + <entry name="RightSideTopPixmapName" key="RightSideTopName" type="String" > + <label>The name of the file to use as the side image in the TDE Menu</label> + <default>kside_top_right.png</default> + </entry> + + <entry name="SideTopTileName" key="SideTopTileName" type="String" > + <label>The name of the file used as a tile to fill the height of TDE Menu that SidePixmapName does not cover</label> + <default>kside_top_tile.png</default> + </entry> + + <entry name="SidePixmapName" key="SideName" type="String" > + <label>The name of the file to use as the side image in the TDE Menu</label> + <default>kside.png</default> + </entry> + + <entry name="SideTileName" key="SideTileName" type="String" > + <label>The name of the file used as a tile to fill the height of TDE Menu that SidePixmapName does not cover</label> + <default>kside_tile.png</default> + </entry> + + <entry name="ShowKMenuText" key="ShowText" type="Bool" > + <label>Show text on the TDE Menu button</label> + <default>false</default> + </entry> + + <entry name="KMenuText" key="Text" type="String" > + <label>Text to be shown on TDE Menu Button</label> + <default code="true">i18n("Applications")</default> + </entry> + + <entry name="CustomKMenuIcon" key="CustomIcon" type="Path" > + <label>Custom TDE Menu Button Icon</label> + <default code="true">QString("kmenu")</default> + </entry> + +</group> + +<group name="buttons" > + +<entry name="ShowMouseOverEffects" key="EnableIconZoom" type="Bool" > + <label>Enable icon mouse over effects</label> + <default>true</default> + </entry> + +<entry name="MouseOversShowIcon" type="Bool" > + <label>Show icons in mouse over effects</label> + <default>true</default> + </entry> + +<entry name="MouseOversShowText" type="Bool" > + <label>Show text in mouse over effects</label> + <default>true</default> + </entry> + +<entry name="MouseOversSpeed" type="Int" > + <label>Controls how fast the tooltips fade in, measured in thousandths of a second</label> + <default>500</default> + <min>0</min> + </entry> + + <entry name="MouseOversShowDelay" type="UInt" > + <label>Mouse over effects are shown after the defined time (in milliseconds)</label> + <default>500</default> + </entry> + + <entry name="MouseOversHideDelay" type="UInt" > + <label>Mouse over effects are hidden after the defined time (in milliseconds)</label> + <default>200</default> + </entry> + +<entry name="EnableTileBackground" type="Bool" > + <label>Enable background tiles</label> + <default>false</default> + </entry> + +<entry name="IconMargin" key="IconMargin" type="Int" > + <label>The margin between panel icons and the panel border</label> + <default>3</default> + </entry> + +<entry name="MaximumTDEMenuButtonHeight" key="MaximumTDEMenuButtonHeight" type="Int" > + <label>The maximum height of the TDE Menu button in pixels</label> + <default>30</default> + </entry> + +<entry name="RemoveButtonsWhenBroken" type="Bool" > + <label>Buttons that represent KServices (applications, primarily) watch for the removal of the service and delete themselves when this happens. This setting turns this off.</label> + <default>true</default> + </entry> + +<entry name="ButtonFont" key="Font" type="Font" > + <label>Font for the buttons with text.</label> + <default code="true">TDEGlobalSettings::generalFont()</default> + </entry> + +<entry name="ButtonTextColor" key="TextColor" type="Color" > + <label>Text color for the buttons.</label> + <default code="true">TDEGlobalSettings::textColor()</default> + </entry> + +</group> + + <group name="SearchField"> + <entry key="History" type="PathList"> + <default></default> + <label></label> + <whatsthis></whatsthis> + </entry> + <entry key="HistoryLength" type="Int"> + <default>50</default> + <label></label> + <whatsthis></whatsthis> + </entry> + <entry key="CompletionItems" type="PathList"> + <default></default> + <label></label> + <whatsthis></whatsthis> + </entry> + <entry key="CompletionMode" type="Int"> + <default>2</default> + <label></label> + <whatsthis></whatsthis> + </entry> + </group> + +</kcfg> + + diff --git a/kicker/libkicker/kickerSettings.kcfgc b/kicker/libkicker/kickerSettings.kcfgc new file mode 100644 index 000000000..8e0b42d93 --- /dev/null +++ b/kicker/libkicker/kickerSettings.kcfgc @@ -0,0 +1,8 @@ +File=kickerSettings.kcfg +Singleton=true +ClassName=KickerSettings +Mutators=true +Visibility=KDE_EXPORT +IncludeFiles=tqapplication.h +GlobalEnums=true +MemberVariables=dpointer diff --git a/kicker/libkicker/kickertip.cpp b/kicker/libkicker/kickertip.cpp new file mode 100644 index 000000000..0a6000f37 --- /dev/null +++ b/kicker/libkicker/kickertip.cpp @@ -0,0 +1,568 @@ +/***************************************************************** + +Copyright (c) 2004 Zack Rusin <[email protected]> + Sami Kyostil <[email protected]> + Aaron J. Seigo <[email protected]> + +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 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 <tqapplication.h> +#include <tqpainter.h> +#include <tqsimplerichtext.h> +#include <tqtimer.h> +#include <tqtooltip.h> + +#include <kdialog.h> + +#include "global.h" + +#include "kickertip.h" +#include "kickerSettings.h" + +// putting this #include higher results in compile errors +#include <netwm.h> +#include <assert.h> + +static const int DEFAULT_FRAMES_PER_SECOND = 30; + +KickerTip* KickerTip::m_self = 0; +int KickerTip::m_tippingEnabled = 1; + +void KickerTip::Client::updateKickerTip() const +{ + if (KickerTip::the()->isTippingFor(dynamic_cast<const TQWidget*>(this)) && + KickerTip::the()->isVisible()) + { + KickerTip::the()->display(); + } +} + +KickerTip* KickerTip::the() +{ + if (!m_self) + { + m_self = new KickerTip(0); + } + + return m_self; +} + +KickerTip::KickerTip(TQWidget * parent) + : TQWidget(parent, "animtt",WX11BypassWM), + m_richText(0), + m_mimeFactory(0), + m_dissolveSize(0), + m_dissolveDelta(-1), + m_direction(KPanelApplet::Up), + m_dirty(false), + m_tippingFor(0), + m_timer(0, "KickerTip::m_timer"), + m_frameTimer(0, "KickerTip::m_frameTimer") +{ + setFocusPolicy(TQ_NoFocus); + setBackgroundMode(NoBackground); + resize(0, 0); + hide(); + connect(&m_frameTimer, TQT_SIGNAL(timeout()), TQT_SLOT(internalUpdate())); +// // FIXME: The settingsChanged(SettingsCategory) signal is not available under Trinity; where was it originally supposed to come from? +// connect(kapp, TQT_SIGNAL(settingsChanged(SettingsCategory)), TQT_SLOT(slotSettingsChanged())); +} + +KickerTip::~KickerTip() +{ + delete m_richText; + delete m_mimeFactory; +} + +void KickerTip::slotSettingsChanged() +{ + TQToolTip::setGloballyEnabled(KickerSettings::showToolTips()); +} + +void KickerTip::display() +{ + if (!tippingEnabled()) + { + return; + } + + { + // prevent tips from showing when the active window is fullscreened + NETRootInfo ri(tqt_xdisplay(), NET::ActiveWindow); + NETWinInfo wi(tqt_xdisplay(), ri.activeWindow(), ri.rootWindow(), NET::WMState); + if (wi.state() & NET::FullScreen) + { + return; + } + } + + TQWidget *widget = const_cast<TQWidget*>(m_tippingFor); + KickerTip::Client *client = dynamic_cast<KickerTip::Client*>(widget); + + if (!client) + { + return; + } + + // delete the mimefactory and create a new one so any old pixmaps used in the + // richtext area are freed but the mimefactory is ready to be added to in + // the call to updateKickerTip + delete m_mimeFactory; + m_mimeFactory = new TQMimeSourceFactory(); + + // Declare interchange object and define defaults. + Data data; + data.maskEffect = Dissolve; + data.duration = 2000; + data.direction = KPanelApplet::Up; + data.mimeFactory = m_mimeFactory; + + // Tickle the information out of the bastard. + client->updateKickerTip(data); + + // Hide the tip if there is nothing to show + if (data.message.isEmpty() && data.subtext.isEmpty() && data.icon.isNull()) + { + hide(); + return; + } + + delete m_richText; + m_richText = new TQSimpleRichText("<qt><h3>" + data.message + "</h3><p>" + + data.subtext + "</p></qt>", font(), TQString(), 0, + m_mimeFactory); + m_richText->setWidth(640); + m_direction = data.direction; + + if (KickerSettings::mouseOversShowIcon()) + { + m_icon = data.icon; + } + else if (KickerSettings::mouseOversShowText()) + { + m_icon = TQPixmap(); + } + else + { + // don't bother since we have NOTHING to show + return; + } + + m_maskEffect = isVisible() ? Plain : data.maskEffect; + m_dissolveSize = 24; + m_dissolveDelta = -1; + + displayInternal(); + + m_frameTimer.start(1000 / DEFAULT_FRAMES_PER_SECOND); + + // close the message window after given mS + if (data.duration > 0) + { + disconnect(&m_timer, TQT_SIGNAL(timeout()), 0, 0); + connect(&m_timer, TQT_SIGNAL(timeout()), TQT_SLOT(hide())); + m_timer.start(data.duration, true); + } + else + { + m_timer.stop(); + } + + move(KickerLib::popupPosition(m_direction, this, m_tippingFor)); + show(); +} + +void KickerTip::paintEvent(TQPaintEvent * e) +{ + if (m_dirty) + { + displayInternal(); + m_dirty = false; + } + + TQPainter p(this); + p.drawPixmap(e->rect().topLeft(), m_pixmap, e->rect()); +} + +void KickerTip::mousePressEvent(TQMouseEvent * /*e*/) +{ + m_timer.stop(); + hide(); +} + +static void drawRoundRect(TQPainter &p, const TQRect &r) +{ + static int line[8] = { 1, 3, 4, 5, 6, 7, 7, 8 }; + static int border[8] = { 1, 2, 1, 1, 1, 1, 1, 1 }; + int xl, xr, y1, y2; + TQPen pen = p.pen(); + bool drawBorder = pen.style() != TQPen::NoPen; + + if (r.width() < 16 || r.height() < 16) + { + p.drawRect(r); + return; + } + + p.fillRect(r.x(), r.y() + 8, r.width(), r.height() - 16, p.brush()); + p.fillRect(r.x() + 8, r.y(), r.width() - 16, r.height(), p.brush()); + + p.setPen(p.brush().color()); + + for (int i = 0; i < 8; i++) + { + xl = i; + xr = r.width() - i - 1; + y1 = 7; + y2 = 7 - (line[i] - 1); + + p.drawLine(xl, y1, xl, y2); + p.drawLine(xr, y1, xr, y2); + + y1 = r.height() - y1 - 1; + y2 = r.height() - y2 - 1; + + p.drawLine(xl, y1, xl, y2); + p.drawLine(xr, y1, xr, y2); + + } + + if (drawBorder) + { + p.setPen(pen); + + if (r.height() > 16) + { + p.drawLine(r.x(), r.y() + 8, r.x(), r.y() + r.height() - 9); + p.drawLine(r.x() + r.width() - 1, r.y() + 8, r.x() + r.width() - 1, r.y() + r.height() - 9); + } + if (r.width() > 16) + { + p.drawLine(r.x() + 8, r.y(), r.x() + r.width() - 9, r.y()); + p.drawLine(r.x() + 8, r.y() + r.height() - 1, r.x() + r.width() - 9, r.y() + r.height() - 1); + } + + for (int i = 0; i < 8; i++) + { + xl = i; + xr = r.width() - i - 1; + y2 = 7 - (line[i] - 1); + y1 = y2 + (border[i] - 1); + + p.drawLine(xl, y1, xl, y2); + p.drawLine(xr, y1, xr, y2); + + y1 = r.height() - y1 - 1; + y2 = r.height() - y2 - 1; + + p.drawLine(xl, y1, xl, y2); + p.drawLine(xr, y1, xr, y2); + + } + } +} + +void KickerTip::plainMask() +{ + TQPainter maskPainter(&m_mask); + + m_mask.fill(Qt::color0); + + maskPainter.setBrush(Qt::color1); + maskPainter.setPen(Qt::NoPen); + //maskPainter.drawRoundRect(m_mask.rect(), 1600 / m_mask.rect().width(), 1600 / m_mask.rect().height()); + drawRoundRect(maskPainter, m_mask.rect()); + setMask(m_mask); + m_frameTimer.stop(); +} + +void KickerTip::dissolveMask() +{ + TQPainter maskPainter(&m_mask); + + m_mask.fill(Qt::color0); + + maskPainter.setBrush(Qt::color1); + maskPainter.setPen(Qt::NoPen); + //maskPainter.drawRoundRect(m_mask.rect(), 1600 / m_mask.rect().width(), 1600 / m_mask.rect().height()); + drawRoundRect(maskPainter, m_mask.rect()); + + m_dissolveSize += m_dissolveDelta; + + if (m_dissolveSize > 0) + { + maskPainter.setRasterOp(TQt::EraseROP); + + int x, y, s; + const int size = 16; + + for (y = 0; y < height() + size; y += size) + { + x = width(); + s = 4 * m_dissolveSize * x / 128; + for (; x > -size; x -= size, s -= 2) + { + if (s < 0) + { + break; + } + maskPainter.drawEllipse(x - s / 2, y - s / 2, s, s); + } + } + } + else if (m_dissolveSize < 0) + { + m_frameTimer.stop(); + m_dissolveDelta = 1; + } + + setMask(m_mask); +} + +void KickerTip::displayInternal() +{ + // we need to check for m_tippingFor here as well as m_richText + // since if one is really persistant and moves the mouse around very fast + // you can trigger a situation where m_tippingFor gets reset to 0 but + // before display() is called! + if (!m_tippingFor || !m_richText) + { + return; + } + + // determine text rectangle + TQRect textRect(0, 0, 0, 0); + if (KickerSettings::mouseOversShowText()) + { + textRect.setWidth(m_richText->widthUsed()); + textRect.setHeight(m_richText->height()); + } + + int margin = KDialog::marginHint(); + int height = TQMAX(m_icon.height(), textRect.height()) + 2 * margin; + int textX = m_icon.isNull() ? margin : 2 + m_icon.width() + 2 * margin; + int width = textX + textRect.width() + margin; + int textY = (height - textRect.height()) / 2; + + // resize pixmap, mask and widget + bool firstTime = m_dissolveSize == 24; + if (firstTime) + { + m_mask.resize(width, height); + m_pixmap.resize(width, height); + resize(width, height); + if (isVisible()) + { + // we've already been shown before, but we may grow larger. + // in the case of Up or Right displaying tips, this growth can + // result in the tip occluding the panel and causing it to redraw + // once we return back to display() causing horrid flicker + move(KickerLib::popupPosition(m_direction, this, m_tippingFor)); + } + } + + // create and set transparency mask + switch(m_maskEffect) + { + case Plain: + plainMask(); + break; + + case Dissolve: + dissolveMask(); + break; + } + + // draw background + TQPainter bufferPainter(&m_pixmap); + bufferPainter.setPen(colorGroup().foreground()); + bufferPainter.setBrush(colorGroup().background()); + //bufferPainter.drawRoundRect(0, 0, width, height, 1600 / width, 1600 / height); + drawRoundRect(bufferPainter, TQRect(0, 0, width, height)); + + // draw icon if present + if (!m_icon.isNull()) + { + bufferPainter.drawPixmap(margin, + margin, + m_icon, 0, 0, + m_icon.width(), m_icon.height()); + } + + if (KickerSettings::mouseOversShowText()) + { + // draw text shadow + TQColorGroup cg = colorGroup(); + cg.setColor(TQColorGroup::Text, cg.background().dark(115)); + int shadowOffset = TQApplication::reverseLayout() ? -1 : 1; + m_richText->draw(&bufferPainter, textX + shadowOffset, textY + 1, TQRect(), cg); + + // draw text + cg = colorGroup(); + m_richText->draw(&bufferPainter, textX, textY, rect(), cg); + } +} + +void KickerTip::tipFor(const TQWidget* w) +{ + if (m_tippingFor) + { + disconnect(m_tippingFor, TQT_SIGNAL(destroyed(TQObject*)), + this, TQT_SLOT(tipperDestroyed(TQObject*))); + } + + m_tippingFor = w; + + if (m_tippingFor) + { + connect(m_tippingFor, TQT_SIGNAL(destroyed(TQObject*)), + this, TQT_SLOT(tipperDestroyed(TQObject*))); + } +} + +void KickerTip::untipFor(const TQWidget* w) +{ + if (isTippingFor(w)) + hide(); +} + +bool KickerTip::isTippingFor(const TQWidget* w) const +{ + return m_tippingFor == w; +} + +void KickerTip::tipperDestroyed(TQObject* o) +{ + // we can't do a dynamic cast because we are in the process of dying + // so static it is. + untipFor(TQT_TQWIDGET(o)); +} + +void KickerTip::internalUpdate() +{ + m_dirty = true; + repaint(false); +} + +void KickerTip::enableTipping(bool tip) +{ + if (tip) + { + m_tippingEnabled++; + } + else + { + m_tippingEnabled--; + } + +// assert(m_tippingEnabled >= -1); + + if (m_tippingEnabled < 1 && m_self) + { + m_self->m_timer.stop(); + m_self->hide(); + } +} + +bool KickerTip::tippingEnabled() +{ + return m_tippingEnabled > 0; +} + +void KickerTip::hide() +{ + tipFor(0); + m_timer.stop(); + m_frameTimer.stop(); + TQWidget::hide(); + + TQToolTip::setGloballyEnabled(KickerSettings::showToolTips()); +} + +bool KickerTip::eventFilter(TQObject *object, TQEvent *event) +{ + if (!tippingEnabled()) + { + return false; + } + + if (!object->isWidgetType()) + { + return false; + } + + TQWidget *widget = TQT_TQWIDGET(object); + + switch (event->type()) + { + case TQEvent::Enter: + if (!KickerSettings::showMouseOverEffects()) + { + return false; + } + + if (!mouseGrabber() && + !tqApp->activePopupWidget() && + !isTippingFor(widget)) + { + TQToolTip::setGloballyEnabled(false); + + tipFor(widget); + m_timer.stop(); + disconnect(&m_timer, TQT_SIGNAL(timeout()), 0, 0); + connect(&m_timer, TQT_SIGNAL(timeout()), TQT_SLOT(display())); + + // delay to avoid false starts + // e.g. when the user quickly zooms their mouse over + // a button then out of kicker + if (isVisible()) + { + m_timer.start(150, true); + } + else + { + m_timer.start(KickerSettings::mouseOversShowDelay(), true); + } + } + break; + case TQEvent::Leave: + m_timer.stop(); + + if (isTippingFor(widget) && isVisible()) + { + disconnect(&m_timer, TQT_SIGNAL(timeout()), 0, 0); + connect(&m_timer, TQT_SIGNAL(timeout()), TQT_SLOT(hide())); + m_timer.start(KickerSettings::mouseOversHideDelay(), true); + } + + tipFor(0); + break; + case TQEvent::MouseButtonPress: + m_timer.stop(); + hide(); + default: + break; + } + + return false; +} + +#include <kickertip.moc> + diff --git a/kicker/libkicker/kickertip.h b/kicker/libkicker/kickertip.h new file mode 100644 index 000000000..b7332967f --- /dev/null +++ b/kicker/libkicker/kickertip.h @@ -0,0 +1,121 @@ +/***************************************************************** + +Copyright (c) 2004 Zack Rusin <[email protected]> + Sami Kyostil <[email protected]> + Aaron J. Seigo <[email protected]> + +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 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 KICKER_TIP_H +#define KICKER_TIP_H + +#include <tqbitmap.h> +#include <tqpixmap.h> +#include <tqtimer.h> +#include <tqwidget.h> + +#include <kpanelapplet.h> + +class TQMimeSourceFactory; +class TQPaintEvent; +class TQSimpleRichText; +class TQTimer; + +class KDE_EXPORT KickerTip : public TQWidget +{ + Q_OBJECT + +public: + enum MaskEffect { Plain, Dissolve }; + + struct Data + { + TQString message; + TQString subtext; + TQPixmap icon; + KickerTip::MaskEffect maskEffect; + int duration; + KPanelApplet::Direction direction; + + // do NOT delete this in the client! + TQMimeSourceFactory* mimeFactory; + }; + + class KDE_EXPORT Client + { + public: + virtual void updateKickerTip(KickerTip::Data&) = 0; + void updateKickerTip() const; + }; + + static KickerTip* the(); + static void enableTipping(bool tip); + static bool tippingEnabled(); + + void untipFor(const TQWidget* w); + bool eventFilter(TQObject *o, TQEvent *e); + +protected: + KickerTip(TQWidget * parent); + ~KickerTip(); + + void paintEvent(TQPaintEvent * e); + void mousePressEvent(TQMouseEvent * e); + + void plainMask(); + void dissolveMask(); + + void displayInternal(); + void hide(); + + void tipFor(const TQWidget* w); + bool isTippingFor(const TQWidget* w) const; + +protected slots: + void tipperDestroyed(TQObject* o); + void internalUpdate(); + void display(); + void slotSettingsChanged(); + +private: + TQBitmap m_mask; + TQPixmap m_pixmap; + TQPixmap m_icon; + MaskEffect m_maskEffect; + TQSimpleRichText* m_richText; + TQMimeSourceFactory* m_mimeFactory; + + int m_dissolveSize; + int m_dissolveDelta; + KPanelApplet::Direction m_direction; + + TQTimer m_timer; + TQTimer m_frameTimer; + bool m_dirty; + + const TQWidget* m_tippingFor; + + static KickerTip* m_self; + static int m_tippingEnabled; + + friend class KickerTip::Client; +}; + +#endif diff --git a/kicker/libkicker/kshadowengine.cpp b/kicker/libkicker/kshadowengine.cpp new file mode 100644 index 000000000..a933026d5 --- /dev/null +++ b/kicker/libkicker/kshadowengine.cpp @@ -0,0 +1,251 @@ +/* This file is proposed to be part of the KDE libraries. + * Copyright (C) 2003 Laur Ivan <[email protected]> + * + * Many thanks to: + * - Bernardo Hung <[email protected]> for the enhanced shadow + * algorithm (currently used) + * - Tim Jansen <[email protected]> for the API updates and fixes. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include <tqcolor.h> +#include <tqpainter.h> +#include <tqbitmap.h> +#include <tqpixmap.h> + +#include "kshadowsettings.h" +#include "kshadowengine.h" + +KShadowEngine::KShadowEngine() : + m_shadowSettings( new KShadowSettings ) +{ +} + +KShadowEngine::~KShadowEngine() +{ + delete m_shadowSettings; +} + +KShadowEngine::KShadowEngine(KShadowSettings *fx) : + m_shadowSettings(0L) +{ + setShadowSettings(fx); +} + + +void KShadowEngine::setShadowSettings(KShadowSettings *fx) +{ + delete m_shadowSettings; + + m_shadowSettings = fx; +} + +KShadowSettings *KShadowEngine::shadowSettings() +{ + return m_shadowSettings; +} + +TQImage KShadowEngine::makeShadow(const TQPixmap& textPixmap, const TQColor &bgColor) +{ + TQImage result; + + // create a new image for for the shaddow + int w = textPixmap.width(); + int h = textPixmap.height(); + + // avoid calling these methods for every pixel + int bgRed = bgColor.red(); + int bgGreen = bgColor.green(); + int bgBlue = bgColor.blue(); + + int thick = m_shadowSettings->thickness() >> 1; + + double alphaShadow; + + /* + * This is the source pixmap + */ + TQImage img = TQImage(textPixmap.convertToImage()).convertDepth(32); + + /* + * Resize the image if necessary + */ + if ((result.width() != w) || (result.height() != h)) + { + result.create(w, h, 32); + } + + result.fill(0); // all black + result.setAlphaBuffer(true); + + for (int i = thick; i < w - thick; i++) + { + for (int j = thick; j < h - thick; j++) + { + switch (m_shadowSettings->algorithm()) + { + case KShadowSettings::DoubleLinearDecay: + alphaShadow = doubleLinearDecay(img, i, j); + break; + case KShadowSettings::RadialDecay: + alphaShadow = radialDecay(img, i, j); + break; + case KShadowSettings::NoDecay: + alphaShadow = noDecay(img, i, j); + break; + case KShadowSettings::DefaultDecay: + default: + alphaShadow = defaultDecay(img, i, j); + } + + alphaShadow = (alphaShadow > m_shadowSettings->maxOpacity()) ? m_shadowSettings->maxOpacity() : alphaShadow; + + // update the shadow's i,j pixel. + result.setPixel(i,j, tqRgba(bgRed, bgGreen , bgBlue, (int) alphaShadow)); + } + } + return result; +} + +// Multiplication factor for pixels directly above, under, or next to the text +#define AXIS_FACTOR 2.0 +// Multiplication factor for pixels diagonal to the text +#define DIAGONAL_FACTOR 1.0 + +double KShadowEngine::defaultDecay(TQImage& source, int i, int j) +{ + if ((i < 1) || (j < 1) || (i > source.width() - 2) || (j > source.height() - 2)) + return 0; + + double alphaShadow; + alphaShadow =(tqGray(source.pixel(i-1,j-1)) * DIAGONAL_FACTOR + + tqGray(source.pixel(i-1,j )) * AXIS_FACTOR + + tqGray(source.pixel(i-1,j+1)) * DIAGONAL_FACTOR + + tqGray(source.pixel(i ,j-1)) * AXIS_FACTOR + + 0 + + tqGray(source.pixel(i ,j+1)) * AXIS_FACTOR + + tqGray(source.pixel(i+1,j-1)) * DIAGONAL_FACTOR + + tqGray(source.pixel(i+1,j )) * AXIS_FACTOR + + tqGray(source.pixel(i+1,j+1)) * DIAGONAL_FACTOR) / m_shadowSettings->multiplicationFactor(); + + return alphaShadow; +} + +double KShadowEngine::doubleLinearDecay(TQImage& source, int i, int j) +{ + //printf("img: %p, %d %d\n", (char *) &source, i, j); + return defaultDecay( source, i, j ); // for now +} + +double KShadowEngine::radialDecay(TQImage& source, int i, int j) +{ + //printf("img: %p, %d %d\n", (char *) &source, i, j); + return defaultDecay( source, i, j ); // for now +} + +double KShadowEngine::noDecay(TQImage& source, int i, int j) +{ + // create a new image for for the shaddow + int w = source.width(); + int h = source.height(); + int sx, sy; + //int thick = m_shadowSettings->thickness() >> 1; + + double alphaShadow = 0; + double opacity = 0; + for (int k = 1; k <= m_shadowSettings->thickness(); k++) { + /* Generate a shadow THICKNESS pixels thicker + * on either side than the text image. Ensure + * that i +/- k and j +/- k are within the + * bounds of the text pixmap. + */ + opacity = 0; + for (int l = -k; l <= k; l++) { + if (i < k) + sx = 0; + else if (i >= w - k) + sx = w - 1; + else + sx = i + l; + + for (int m = -k; m <= k; m++) { + if (j < k) + sy = 0; + else if (j >= h - k) + sy = h - 1; + else + sy = j + m; + + opacity += tqGray(source.pixel(sx, sy)); + } + } + alphaShadow += opacity / m_shadowSettings->multiplicationFactor(); + } + return alphaShadow; +} + +KTextShadowEngine::KTextShadowEngine() : KShadowEngine() +{ + KShadowSettings *shadset = new KShadowSettings(); + + shadset->setOffsetX(0); + shadset->setOffsetY(0); + shadset->setThickness(1); + shadset->setMaxOpacity(96); + + setShadowSettings(shadset); +} + +// taken from mtaskbar, by Sebastian Wolff +void KTextShadowEngine::drawText(TQPainter &p, const TQRect &tr, int tf, const TQString &str, const TQSize &size) +{ + // get the color of the shadow: white for dark text, black for bright text + TQPen textPen = p.pen(); + TQColor shadCol = textPen.color(); + + if (shadCol.red() + + shadCol.green() + + shadCol.blue() <= 3*256/2-1) + { + shadCol = TQColor(255,255,255); + } + else + { + shadCol = TQColor(0,0,0); + } + + // get a transparent pixmap + TQPainter pixPainter; + TQPixmap textPixmap(size); + + textPixmap.fill(TQColor(0,0,0)); + textPixmap.setMask(textPixmap.createHeuristicMask(true)); + + // draw text + pixPainter.begin(&textPixmap); + pixPainter.setPen(Qt::white); + pixPainter.setFont(p.font()); // get the font from the root painter + pixPainter.drawText(tr, tf, str); + pixPainter.end(); + + // draw shadow + TQImage img = makeShadow(textPixmap, shadCol); + + // return + p.drawImage(0, 0, img); + p.drawText(tr, tf, str); +} + diff --git a/kicker/libkicker/kshadowengine.h b/kicker/libkicker/kshadowengine.h new file mode 100644 index 000000000..1ddc093ff --- /dev/null +++ b/kicker/libkicker/kshadowengine.h @@ -0,0 +1,123 @@ +/* This file is proposed to be part of the KDE libraries. + * Copyright (C) 2003 Laur Ivan <[email protected]> + * + * Many thanks to: + * - Bernardo Hung <[email protected]> for the enhanced shadow + * algorithm (currently used) + * - Tim Jansen <[email protected]> for the API updates and fixes. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __FX_SHADOW +#define __FX_SHADOW + +#include <tqpixmap.h> +#include <tqimage.h> +#include <tqcolor.h> + +#include <kdemacros.h> + +class KShadowSettings; + +/** + * This class implements the shadow algorithm(s). It uses a FxData + * object for its parameters. Note that the shadow algorithm is using the + * luminosity of the original pixmap for the shadow one. + * @see KShadowSettings + * @author [email protected] + * @since 3.2 + */ +class KDE_EXPORT KShadowEngine +{ +public: + /// Creates a new shadow engine. + KShadowEngine(); + + ~KShadowEngine(); + + /** + * Creates a new shadow engine. + * @param fx the shadow settings object with the configuration. The Shadow + * Engine will own this object and also delete it. Must + * be heap-allocated + */ + KShadowEngine(KShadowSettings *fx); + + /** + * Set the KShadowSettings object. + * @param fx the shadow settings object with the configuration. The Shadow + * Engine will own this object and also delete it. Must + * be heap-allocated. + */ + void setShadowSettings(KShadowSettings *fx); + + /** + * Get the current KShadowSettings. + * @param the current shadow settings + */ + KShadowSettings *shadowSettings(); + + /** + * Make shadow! + * + * textPixmap is the original pixmap where a (white) text is drawn. + * bgColor is the color used for the shadow. + * @param textPixmap the pixmap of the text + * @param bgColor the background color + * @return the resulting image + */ + TQImage makeShadow(const TQPixmap& textPixmap, const TQColor &bgColor); + +private: + // No static objects in libs, and no static deleters in tdefx... + //static KShadowSettings s_defaultShadowSettings; + + KShadowSettings *m_shadowSettings; + + /* + * a simple algorithm with 3 pixels thickness + */ + double defaultDecay(TQImage& source, int x, int y); + + /* + * a slower algorithm where the influence of a pixel + * is tqGray(px)/(abs(dx) + abs(dy) +1). + */ + double doubleLinearDecay(TQImage& source, int x, int y); + + /* + * a very slow algorithm where the influence of a pixel + * is tqGray(px)/(sqrt(sqr(dx) + sqr(dy)) +1). + */ + double radialDecay(TQImage& source, int x, int y); + + /* + * a nice/fast algorithm proposed by Bernardo Hung + */ + double noDecay(TQImage& source, int x, int y); + + void *d; +}; + +class KDE_EXPORT KTextShadowEngine : public KShadowEngine +{ +public: + KTextShadowEngine(); + + void drawText(TQPainter &p, const TQRect &tr, int tf, const TQString &str, const TQSize &size); +}; + +#endif diff --git a/kicker/libkicker/kshadowsettings.cpp b/kicker/libkicker/kshadowsettings.cpp new file mode 100644 index 000000000..4d6bce5c3 --- /dev/null +++ b/kicker/libkicker/kshadowsettings.cpp @@ -0,0 +1,182 @@ +/* This file is proposed to be part of the KDE libraries. + * Copyright (C) 2003 Laur Ivan <[email protected]> + * + * Many thanks to: + * - Tim Jansen <[email protected]> for the API updates and fixes. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include <tqstring.h> +#include <tqstringlist.h> +#include "kshadowsettings.h" + +KShadowSettings::KShadowSettings() +{ + // init the components with some default values + setDefaults(); +} + +// load/save methods +void KShadowSettings::fromString(const TQString &val) +{ + setOffsetX(val.section(',', OFFSET_X, OFFSET_X).toInt()); + setOffsetY(val.section(',', OFFSET_Y, OFFSET_Y).toInt()); + setMultiplicationFactor(val.section(',', MULTIPLICATION_FACTOR, MULTIPLICATION_FACTOR).toDouble()); + setMaxOpacity(val.section(',', MAX_OPACITY, MAX_OPACITY).toDouble()); + setThickness(val.section(',', THICKNESS, THICKNESS).toInt()); + setAlgorithm((Algorithm) val.section(',', ALGORITHM, ALGORITHM).toInt()); + setSelectionType((SelectionType)val.section(',', SELECTION_TYPE, SELECTION_TYPE).toInt()); +} + +TQString KShadowSettings::toString() const +{ + TQString result; + result.sprintf("%d,%d,%f,%f,%d,%d,%d", + offsetX(), + offsetY(), + multiplicationFactor(), + maxOpacity(), + thickness(), + (int)algorithm(), + (int)selectionType()); + return result; +} + +//*********************************** +// get methods +//*********************************** + +/** + * Returns the decay algorithm to be used (see the alg. enumeration in the .h) + */ +KShadowSettings::Algorithm KShadowSettings::algorithm() const +{ + return _algorithm; +} + +/** + * Returns a multiplication facor used to average the resulted data + */ +double KShadowSettings::multiplicationFactor() const +{ + return _multiplicationFactor; +} + +/** + * Returns the max opacity allowed (0 = transparent, 255 = opaque) + */ +double KShadowSettings::maxOpacity() const +{ + return _maxOpacity; +} + +/** + * Returns the Y offset (0 is centered on text) + */ +int KShadowSettings::offsetX() const +{ + return _offsetX; +} + +/** + * Returns the Y offset (0 is centered on text) + */ +int KShadowSettings::offsetY() const +{ + return _offsetY; +} + +/** + * Returns the thickness. Used by the KShadow algorithm + */ +int KShadowSettings::thickness() const +{ + return _thickness; +} + +/** + * Returns the selection type + */ +KShadowSettings::SelectionType KShadowSettings::selectionType() const +{ + return _selectionType; +} + +// set methods +/** + * set the default parameters + */ +void KShadowSettings::setDefaults() +{ + fromString(DEFAULT_SHADOW_CONFIGURATION); +} + + +/** + * Set the algorithm + */ +void KShadowSettings::setAlgorithm(Algorithm val) +{ + _algorithm = val; +} + +/** + * Set the multiplication factor + */ +void KShadowSettings::setMultiplicationFactor(double val) +{ + _multiplicationFactor = val; +} + +/** + * Set the max. opacity + */ +void KShadowSettings::setMaxOpacity(double val) +{ + _maxOpacity = val; +} + +/** + * Set the X offset of the shadow + */ +void KShadowSettings::setOffsetX(int val) +{ + _offsetX = val; +} + +/** + * Set the Y offset of the shadow + */ +void KShadowSettings::setOffsetY(int val) +{ + _offsetY = val; +} + +/** + * Set the shadow thickness + */ +void KShadowSettings::setThickness(int val) +{ + _thickness = val; +} + +/** + * Set the selection type + */ +void KShadowSettings::setSelectionType(SelectionType val) +{ + _selectionType = val; +} diff --git a/kicker/libkicker/kshadowsettings.h b/kicker/libkicker/kshadowsettings.h new file mode 100644 index 000000000..e222b964d --- /dev/null +++ b/kicker/libkicker/kshadowsettings.h @@ -0,0 +1,236 @@ +/* This file is proposed to be part of the KDE libraries. + * Copyright (C) 2003 Laur Ivan <[email protected]> + * + * Many thanks to: + * - Tim Jansen <[email protected]> for the API updates and fixes. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __FX_DATA +#define __FX_DATA + +#include <kdemacros.h> + +#define SHADOW_CONFIG_ENTRY TQString("ShadowParameters") +#define SHADOW_TEXT_COLOR TQString("ShadowTextColor") +#define SHADOW_TEXT_BACKGROUND TQString("ShadowTextBackground") + +// fallback configuration string +#define DEFAULT_SHADOW_CONFIGURATION TQString("0,0,4.0,120.0,2,1,1,0,0,0") + +/** + * This class is the implementation of a structure for the + * various parameters required by the shadow class. + * + * One may afford this implementation since the shadow class is + * designed to be used as singleton for an application. + * @see KShadowEngine + * @author [email protected] + * @since 3.2 + */ +class KDE_EXPORT KShadowSettings +{ + public: + /** + * Specifies the order of the options. + * @see fromString + */ + enum ConfigurationOrder + { + OFFSET_X = 0, + OFFSET_Y = OFFSET_X + 1, + MULTIPLICATION_FACTOR = OFFSET_Y + 1, + MAX_OPACITY = MULTIPLICATION_FACTOR + 1, + THICKNESS = MAX_OPACITY + 1, + ALGORITHM = THICKNESS + 1, + SELECTION_TYPE = ALGORITHM + 1 + }; + + public: + /** + * The algorithm used. + */ + enum Algorithm + { + DefaultDecay = 1, ///< the default AXIS/DIAGONAL_FACTOR based alg + DoubleLinearDecay, ///< decay factor is 1/dx+dy + RadialDecay, ///< decay factor is 1/sqrt(dx*dx + dy*dy) + NoDecay ///< decay factor is 1 always + }; + + /** + * The selected method used. + */ + enum SelectionType + { + InverseVideoOnSelection = 0, ///< when selected, the halo is on I/Video + SelectionColorsOnSelection ///< the halo is made w/ selected colors + }; + + /** + * The default constructor. + * Creates an object with default settings for all the variabless. + */ + KShadowSettings(); + + // load/save methods + /** + * Loads the configuration from a string. + * @param the string to load from (comma-separated values) + * @see ConfigurationOrder + */ + virtual void fromString(const TQString &s); + /** + * Saves the configuration to a string. + * @return the configuration (comma-separated values) + * @see ConfigurationOrder + */ + virtual TQString toString() const; + + // get methods + /** + * Returns the x offset of the shadow. + * @return the x offset + */ + int offsetX() const; + + /** + * Returns the y offset of the shadow. + * @return the y offset + */ + int offsetY() const; + + /** + * Returns the multiplication factor. + * @return the multiplication factor + */ + double multiplicationFactor() const; + + /** + * Returns the maximum opacity of the shadow. + * @return the maximum opacity + */ + double maxOpacity() const; + + /** + * Returns the thickness. + * @return the thickness + */ + int thickness() const; + + /** + * Returns the used algorithm. + * @return the algorithm used + */ + Algorithm algorithm() const; + + /** + * Returns the selection type used. + * @return the selection type + */ + SelectionType selectionType() const; + + // set methods + /** + * Sets default values. + */ + virtual void setDefaults(); + + /** + * Sets the used algorithm. + * @param a the algorithm used + */ + virtual void setAlgorithm(Algorithm a); + + /** + * Sets the multiplication factor. + * @param mf the multiplication factor + */ + virtual void setMultiplicationFactor(double mf); + + /** + * Sets the maximum opacity of the shadow. + * @param mo the maximum opacity + */ + virtual void setMaxOpacity(double mo); + + /** + * Sets the x offset of the shadow. + * @param x the x offset + */ + virtual void setOffsetX(int x); + + /** + * Sets the y offset of the shadow. + * @param y the y offset + */ + virtual void setOffsetY(int y); + + /** + * Sets the thickness. + * @param t the thickness + */ + virtual void setThickness(int t); + + /** + * Sets the selection type used. + * @param s the selection type + */ + virtual void setSelectionType(SelectionType s); + + private: + + /* + * The employed algorithm (see fxshadow.h) + */ + Algorithm _algorithm; + + /** + * This is the multiplication factor for the resulted shadow + */ + double _multiplicationFactor; + + /** + * The maximum permitted opacity for the shadow + */ + double _maxOpacity; + + /* + * offsetX and offsetY are the x/y offsets of the shadow with + * the mention that 0,0 is a centered shadow. + */ + int _offsetX; + int _offsetY; + + /* + * The shadow thickness: + * shadow is this many pixels thicker than the text. + */ + int _thickness; + + /* + * If the value is InverseVideoOnSelection, then the fg/bg + * colours are swapped when the element is selected. + * Otherwise, the selected fg/bg colors are used for text + * as well + */ + SelectionType _selectionType; + + void *d; +}; + + +#endif diff --git a/kicker/libkicker/menuinfo.cpp b/kicker/libkicker/menuinfo.cpp new file mode 100644 index 000000000..a8e4bf1fa --- /dev/null +++ b/kicker/libkicker/menuinfo.cpp @@ -0,0 +1,68 @@ +/***************************************************************** + +Copyright (c) 1996-2000 the kicker authors. See file AUTHORS. + +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 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 "menuinfo.h" + +#include <tqfile.h> +#include <tqwidget.h> + +#include <tdeapplication.h> +#include <ksimpleconfig.h> +#include <klibloader.h> +#include <kstandarddirs.h> +#include <kpanelmenu.h> +#include <tdeparts/componentfactory.h> + +MenuInfo::MenuInfo(const TQString& desktopFile) +{ + KSimpleConfig df(locate("data", TQString::fromLatin1("kicker/menuext/%1").arg(desktopFile))); + df.setGroup("Desktop Entry"); + + TQStringList list = df.readListEntry("X-TDE-AuthorizeAction"); + if (kapp && !list.isEmpty()) + { + for(TQStringList::ConstIterator it = list.begin(); + it != list.end(); + ++it) + { + if (!kapp->authorize((*it).stripWhiteSpace())) + return; + } + } + + name_ = df.readEntry("Name"); + comment_ = df.readEntry("Comment"); + icon_ = df.readEntry("Icon"); + library_ = df.readEntry("X-TDE-Library"); + desktopfile_ = desktopFile; +} + +KPanelMenu* MenuInfo::load(TQWidget *parent, const char *name) +{ + if (library_.isEmpty()) + return 0; + + return KParts::ComponentFactory::createInstanceFromLibrary<KPanelMenu>( + TQFile::encodeName( library_ ), + TQT_TQOBJECT(parent), name ); +} diff --git a/kicker/libkicker/menuinfo.h b/kicker/libkicker/menuinfo.h new file mode 100644 index 000000000..5925d4826 --- /dev/null +++ b/kicker/libkicker/menuinfo.h @@ -0,0 +1,52 @@ +/***************************************************************** + +Copyright (c) 1996-2000 the kicker authors. See file AUTHORS. + +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 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 _menuinfo_h_ +#define _menuinfo_h_ + +#include <tqstring.h> + +#include <kdemacros.h> + +class KPanelMenu; +class TQWidget; + +class KDE_EXPORT MenuInfo +{ +public: + MenuInfo(const TQString& desktopFile); + + TQString name() const { return name_; } + TQString comment() const { return comment_; } + TQString icon() const { return icon_; } + TQString library() const { return library_; } + TQString desktopFile() const { return desktopfile_; } + bool isValid() const { return !name_.isEmpty(); } + + KPanelMenu* load(TQWidget *parent = 0, const char *name = 0); + +private: + TQString name_, comment_, icon_, library_, desktopfile_; +}; + +#endif diff --git a/kicker/libkicker/panelbutton.cpp b/kicker/libkicker/panelbutton.cpp new file mode 100644 index 000000000..aaac124c2 --- /dev/null +++ b/kicker/libkicker/panelbutton.cpp @@ -0,0 +1,1103 @@ +/***************************************************************** + +Copyright (c) 1996-2000 the kicker authors. See file AUTHORS. + +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 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. + +******************************************************************/ + +#undef None // Qt4 +#include <tqcursor.h> +#include <tqfile.h> +#include <tqfontmetrics.h> +#include <tqpainter.h> +#include <tqpopupmenu.h> +#include <tqstyle.h> +#include <tqstylesheet.h> +#include <tqtooltip.h> +#include <tqpixmap.h> + +#include <tdeapplication.h> +#include <tdeconfig.h> +#include <kcursor.h> +#include <kdialog.h> +#include <kdirwatch.h> +#include <tdeglobal.h> +#include <tdeglobalsettings.h> +#include <kiconloader.h> +#include <kicontheme.h> +#include <kiconeffect.h> +#include <kipc.h> +#include <kstandarddirs.h> +#include <tdelocale.h> +#include <kdebug.h> + +#include "global.h" + +#include "kshadowengine.h" +#include "kshadowsettings.h" + +#include "kickerSettings.h" +#include "panelbutton.h" +#include "panelbutton.moc" + +// For now link these two +#define m_disableHighlighting m_forceStandardCursor + +// init static variable +KShadowEngine* PanelButton::s_textShadowEngine = 0L; + +PanelButton::PanelButton( TQWidget* parent, const char* name, bool forceStandardCursor ) + : TQButton(parent, name), + m_valid(true), + m_isLeftMouseButtonDown(false), + m_drawArrow(false), + m_highlight(false), + m_changeCursorOverItem(forceStandardCursor?false:true), + m_hasAcceptedDrag(false), + m_centerInContainer(true), + m_arrowDirection(KPanelExtension::Bottom), + m_popupDirection(KPanelApplet::Up), + m_iconAlignment(AlignCenter), + m_orientation(Qt::Horizontal), + m_size((TDEIcon::StdSizes)-1), + m_fontPercent(0.40), + m_forceStandardCursor(forceStandardCursor) +{ + setBackgroundOrigin(AncestorOrigin); + setWFlags(TQt::WNoAutoErase); + TDEGlobal::locale()->insertCatalogue("libkicker"); + calculateIconSize(); + setAcceptDrops(true); + + m_textColor = TDEGlobalSettings::textColor(); + + updateSettings(TDEApplication::SETTINGS_MOUSE); + + kapp->addKipcEventMask(KIPC::SettingsChanged | KIPC::IconChanged); + + installEventFilter(KickerTip::the()); + + connect(kapp, TQT_SIGNAL(settingsChanged(int)), TQT_SLOT(updateSettings(int))); + connect(kapp, TQT_SIGNAL(iconChanged(int)), TQT_SLOT(updateIcon(int))); +} + +void PanelButton::configure() +{ + TQString name = tileName(); + if( name.isEmpty() ) + return; + + if (!KickerSettings::enableTileBackground()) + { + setTile(TQString::null); + return; + } + + TDEConfigGroup tilesGroup( TDEGlobal::config(), "button_tiles" ); + if( !tilesGroup.readBoolEntry( "Enable" + name + "Tiles", true ) ) { + setTile( TQString::null ); + return; + } + + TQString tile = tilesGroup.readEntry( name + "Tile" ); + TQColor color = TQColor(); + + if (tile == "Colorize") + { + color = tilesGroup.readColorEntry( name + "TileColor" ); + tile = TQString::null; + } + + setTile( tile, color ); +} + +void PanelButton::setTile(const TQString& tile, const TQColor& color) +{ + if (tile == m_tile && m_tileColor == color) + { + return; + } + + m_tile = tile; + m_tileColor = color; + loadTiles(); + update(); +} + +void PanelButton::setDrawArrow(bool drawArrow) +{ + if (m_drawArrow == drawArrow) + { + return; + } + + m_drawArrow = drawArrow; + update(); +} + +TQImage PanelButton::loadTile(const TQString& tile, + const TQSize& size, + const TQString& state) +{ + TQString name = tile; + + if (size.height() < 42) + { + name += "_tiny_"; + } + else if (size.height() < 54) + { + name += "_normal_"; + } + else + { + name += "_large_"; + } + + name += state + ".png"; + + TQImage tileImg(TDEGlobal::dirs()->findResource("tiles", name)); + + // scale if size does not match exactly + if (!tileImg.isNull() && tileImg.size() != size) + { + tileImg = tileImg.smoothScale(size); + } + + return tileImg; +} + +void PanelButton::setEnabled(bool enable) +{ + TQButton::setEnabled(enable); + loadIcons(); + update(); +} + +void PanelButton::setPopupDirection(KPanelApplet::Direction d) +{ + m_popupDirection = d; + setArrowDirection(KickerLib::directionToPopupPosition(d)); +} + +void PanelButton::setIconAlignment(TQ_Alignment align) +{ + m_iconAlignment = align; + update(); +} + +void PanelButton::setOrientation(Orientation o) +{ + m_orientation = o; +} + +void PanelButton::updateIcon(int group) +{ + if (group != TDEIcon::Panel) + { + return; + } + + loadIcons(); + update(); +} + +void PanelButton::updateSettings(int category) +{ + if (category != TDEApplication::SETTINGS_MOUSE) + { + return; + } + + if (m_forceStandardCursor == FALSE) + m_changeCursorOverItem = TDEGlobalSettings::changeCursorOverIcon(); + else + m_changeCursorOverItem = FALSE; + + if (m_changeCursorOverItem) + { + setCursor(KCursor::handCursor()); + } + else + { + unsetCursor(); + } +} + +void PanelButton::checkForDeletion(const TQString& path) +{ + if (path == m_backingFile) + { + setEnabled(false); + TQTimer::singleShot(1000, this, TQT_SLOT(scheduleForRemoval())); + } +} + +bool PanelButton::checkForBackingFile() +{ + return TQFile::exists(m_backingFile); +} + +void PanelButton::scheduleForRemoval() +{ + static int timelapse = 1000; + if (checkForBackingFile()) + { + setEnabled(true); + timelapse = 1000; + emit hideme(false); + return; + } + else if (KickerSettings::removeButtonsWhenBroken()) + { + if (timelapse > 255*1000) // we'v given it ~8.5 minutes by this point + { + emit removeme(); + return; + } + + if (timelapse > 3000 && isVisible()) + { + emit hideme(true); + } + + timelapse *= 2; + TQTimer::singleShot(timelapse, this, TQT_SLOT(scheduleForRemoval())); + } +} + +// return the dimension that the button wants to be for a given panel dimension (panelDim) +int PanelButton::preferredDimension(int panelDim) const +{ + // determine the upper limit on the size. Normally, this is panelDim, + // but if conserveSpace() is true, we restrict size to comfortably fit the icon + if (KickerSettings::conserveSpace()) + { + int newSize = preferredIconSize(panelDim); + if (newSize > 0) + { + return TQMIN(panelDim, newSize + (KDialog::spacingHint() * 2)); + } + } + + return panelDim; +} + +int PanelButton::widthForHeight(int height) const +{ + int rc = preferredDimension(height); + + // we only paint the text when horizontal, so make sure we're horizontal + // before adding the text in here + if (orientation() == Qt::Horizontal && !m_buttonText.isEmpty()) + { + TQFont f(font()); + //f.setPixelSize(KMIN(height, KMAX(int(float(height) * m_fontPercent), 16))); + TQFontMetrics fm(f); + + rc += fm.width(m_buttonText) + ((KMIN(25, KMAX(5, fm.width('m') / 2)))/2); + //rc += fm.width(m_buttonText); + } + + return rc; +} + +int PanelButton::heightForWidth(int width) const +{ + int rc=preferredDimension(width); + + return rc; +} + +const TQPixmap& PanelButton::labelIcon() const +{ + if (m_disableHighlighting || (!KickerSettings::showMouseOverEffects())) + return m_icon; + else + return m_highlight ? m_iconh : m_icon; +} + +const TQPixmap& PanelButton::zoomIcon() const +{ + return m_iconz; +} + +bool PanelButton::isValid() const +{ + return m_valid; +} + +void PanelButton::setTitle(const TQString& t) +{ + m_title = t; +} + +void PanelButton::setIcon(const TQString& icon) +{ + if (icon == m_iconName) + { + return; + } + + m_iconName = icon; + loadIcons(); + update(); + emit iconChanged(); +} + +TQString PanelButton::icon() const +{ + return m_iconName; +} + +bool PanelButton::hasText() const +{ + return !m_buttonText.isEmpty(); +} + +void PanelButton::setButtonText(const TQString& text) +{ + m_buttonText = text; + update(); +} + +TQString PanelButton::buttonText() const +{ + return m_buttonText; +} + +void PanelButton::setTextColor(const TQColor& c) +{ + m_textColor = c; +} + +TQColor PanelButton::textColor() const +{ + return m_textColor; +} + +void PanelButton::setFontPercent(double p) +{ + m_fontPercent = p; +} + +double PanelButton::fontPercent() const +{ + return m_fontPercent; +} + +KPanelExtension::Orientation PanelButton::orientation() const +{ + return m_orientation; +} + +KPanelApplet::Direction PanelButton::popupDirection() const +{ + return m_popupDirection; +} + +TQPoint PanelButton::center() const +{ + return mapToGlobal(rect().center()); +} + +TQString PanelButton::title() const +{ + return m_title; +} + +void PanelButton::triggerDrag() +{ + setDown(false); + + startDrag(); +} + +void PanelButton::startDrag() +{ + emit dragme(m_icon); +} + +void PanelButton::enterEvent(TQEvent* e) +{ + if (!m_highlight && m_disableHighlighting == FALSE) + { + m_highlight = true; + repaint(false); + } + + TQButton::enterEvent(e); +} + +void PanelButton::leaveEvent(TQEvent* e) +{ + if (m_highlight) + { + m_highlight = false; + repaint(false); + } + + TQButton::leaveEvent(e); +} + +void PanelButton::dragEnterEvent(TQDragEnterEvent* e) +{ + if (e->isAccepted()) + { + m_hasAcceptedDrag = true; + } + + update(); + TQButton::dragEnterEvent( e ); +} + +void PanelButton::dragLeaveEvent(TQDragLeaveEvent* e) +{ + m_hasAcceptedDrag = false; + update(); + TQButton::dragLeaveEvent( e ); +} + +void PanelButton::dropEvent(TQDropEvent* e) +{ + m_hasAcceptedDrag = false; + update(); + TQButton::dropEvent( e ); +} + +void PanelButton::mouseMoveEvent(TQMouseEvent *e) +{ + if (!m_isLeftMouseButtonDown || (e->state() & Qt::LeftButton) == 0) + { + return; + } + + TQPoint p(e->pos() - m_lastLeftMouseButtonPress); + if (p.manhattanLength() <= 16) + { + // TDEGlobalSettings::dndEventDelay() is not enough! + return; + } + + m_isLeftMouseButtonDown = false; + triggerDrag(); +} + +void PanelButton::mousePressEvent(TQMouseEvent *e) +{ + if (e->button() == Qt::LeftButton) + { + m_lastLeftMouseButtonPress = e->pos(); + m_isLeftMouseButtonDown = true; + } + TQButton::mousePressEvent(e); +} + +void PanelButton::mouseReleaseEvent(TQMouseEvent *e) +{ + if (e->button() == Qt::LeftButton) + { + m_isLeftMouseButtonDown = false; + + TQPixmap pix = labelIcon(); + if (KickerSettings::showIconActivationEffect() == true) { + TDEIconEffect::visualActivate(this, this->geometry(), &pix); + } + } + TQButton::mouseReleaseEvent(e); +} + +void PanelButton::resizeEvent(TQResizeEvent*) +{ + loadTiles(); + + if (calculateIconSize()) + { + loadIcons(); + } +} + +void PanelButton::drawButton(TQPainter *p) +{ + const TQPixmap& tile = (isDown() || isOn()) ? m_down : m_up; + + if (m_tileColor.isValid()) + { + p->fillRect(rect(), m_tileColor); + style().tqdrawPrimitive(TQStyle::PE_Panel, p, rect(), colorGroup()); + } + else if (paletteBackgroundPixmap()) + { + // Draw the background. This is always needed, even when using tiles, + // because they don't have to cover the entire button. + TQPoint offset = backgroundOffset(); + int ox = offset.x(); + int oy = offset.y(); + p->drawTiledPixmap( 0, 0, width(), height(),*paletteBackgroundPixmap(), ox, oy); + } + + if (!tile.isNull()) + { + // Draw the tile. + p->drawPixmap(0, 0, tile); + } + else if (isDown() || isOn()) + { + // Draw shapes to indicate the down state. + style().tqdrawPrimitive(TQStyle::PE_Panel, p, rect(), colorGroup(), TQStyle::Style_Sunken); + } + + drawButtonLabel(p); + + if (hasFocus() || m_hasAcceptedDrag) + { + int x1, y1, x2, y2; + TQT_TQRECT_OBJECT(rect()).coords(&x1, &y1, &x2, &y2); + TQRect r(x1+2, y1+2, x2-x1-3, y2-y1-3); + style().tqdrawPrimitive(TQStyle::PE_FocusRect, p, r, colorGroup(), + TQStyle::Style_Default, colorGroup().button()); + } +} + +void PanelButton::drawDeepButton(TQPainter *p) +{ + const TQPixmap& tile = (isDown() || isOn()) ? m_down : m_up; + + if (m_tileColor.isValid()) + { + p->fillRect(rect(), m_tileColor); + style().tqdrawPrimitive(TQStyle::PE_Panel, p, rect(), colorGroup()); + } + else if (paletteBackgroundPixmap()) + { + // Draw the background. This is always needed, even when using tiles, + // because they don't have to cover the entire button. + TQPoint offset = backgroundOffset(); + int ox = offset.x(); + int oy = offset.y(); + p->drawTiledPixmap( 0, 0, width(), height(),*paletteBackgroundPixmap(), ox, oy); + } + + TQRect btn_rect = TQRect(rect().x(), rect().y()+1, rect().width(), rect().height()-2); + if (isDown() || isOn()) { + style().tqdrawPrimitive(TQStyle::PE_ButtonBevel, p, btn_rect, colorGroup(), TQStyle::Style_Down); + } + else { + style().tqdrawPrimitive(TQStyle::PE_ButtonBevel, p, btn_rect, colorGroup(), TQStyle::Style_Raised); + } + + drawButtonLabel(p,0,FALSE); + + if (hasFocus() || m_hasAcceptedDrag) + { + int x1, y1, x2, y2; + TQT_TQRECT_OBJECT(rect()).coords(&x1, &y1, &x2, &y2); + TQRect r(x1+2, y1+2, x2-x1-3, y2-y1-3); + style().tqdrawPrimitive(TQStyle::PE_FocusRect, p, r, colorGroup(), + TQStyle::Style_Default, colorGroup().button()); + } +} + +void PanelButton::drawButtonLabel(TQPainter *p) +{ + drawButtonLabel(p,0,TRUE); +} + +void PanelButton::drawButtonLabel(TQPainter *p, int voffset, bool drawArrow) +{ + TQPixmap icon = labelIcon(); + bool active = isDown() || isOn(); + + int offsetX = 0; + int offsetY = 0; + + if (active && KickerSettings::showDeepButtons()) + { + offsetX = style().pixelMetric(TQStyle::PM_ButtonShiftHorizontal); + offsetY = style().pixelMetric(TQStyle::PM_ButtonShiftVertical); + } + + if (active && !KickerSettings::showDeepButtons()) + { + icon = TQImage(icon.convertToImage()).smoothScale(icon.width() - 2, + icon.height() - 2); + } + + int y = 0; + if (m_iconAlignment & AlignVCenter) + y = (height() - icon.height()) / 2; + else if (m_iconAlignment & AlignBottom) + y = (height() - icon.height()); + + if (!m_buttonText.isEmpty() && orientation() == Qt::Horizontal) + { + int h = height(); + int w = width(); + p->save(); + TQFont f = font(); + + double fontPercent = m_fontPercent; + if (active && !KickerSettings::showDeepButtons()) + { + fontPercent *= .8; + } + //f.setPixelSize(KMIN(h, KMAX(int(float(h) * m_fontPercent), 16))); + TQFontMetrics fm(f); + p->setFont(f); + + /* Draw shadowed text */ + bool reverse = TQApplication::reverseLayout(); + TQPainter::TextDirection rtl = reverse ? TQPainter::RTL : TQPainter::LTR; + + if (!reverse && !icon.isNull()) + { + /* Draw icon */ + p->drawPixmap(offsetX+3, offsetY+y+voffset, icon); + } + + int tX = reverse ? 3 : icon.width() + KMIN(25, KMAX(5, fm.width('m') / 2)); + int tY = fm.ascent() + ((h - fm.height()) / 2); + + TQColor shadCol = KickerLib::shadowColor(m_textColor); + + // get a transparent pixmap + TQPainter pixPainter; + TQPixmap textPixmap(w, h); + + textPixmap.fill(TQColor(0,0,0)); + textPixmap.setMask(textPixmap.createHeuristicMask(true)); + + // draw text + pixPainter.begin(&textPixmap); + pixPainter.setPen(m_textColor); + pixPainter.setFont(p->font()); // get the font from the root painter + pixPainter.drawText(offsetX+tX, offsetY+tY, m_buttonText, -1, rtl); + pixPainter.end(); + + if (!s_textShadowEngine) + { + KShadowSettings* shadset = new KShadowSettings(); + shadset->setOffsetX(0); + shadset->setOffsetY(0); + shadset->setThickness(1); + shadset->setMaxOpacity(96); + s_textShadowEngine = new KShadowEngine(shadset); + } + + // draw shadow + TQImage img = s_textShadowEngine->makeShadow(textPixmap, shadCol); + p->drawImage(offsetX, offsetY, img); + p->save(); + p->setPen(m_textColor); + p->drawText(offsetX+tX, offsetY+tY+voffset, m_buttonText, -1, rtl); + p->restore(); + + if (reverse && !icon.isNull()) + { + p->drawPixmap(offsetX + w - icon.width() - 3, offsetY+y+voffset, icon); + } + + p->restore(); + } + else if (!icon.isNull()) + { + int x = 0; + if (m_iconAlignment & AlignHCenter) + x = (width() - icon.width()) / 2; + else if (m_iconAlignment & AlignRight) + x = (width() - icon.width()); + p->drawPixmap(offsetX+x, offsetY+y+voffset, icon); + } + + if (m_drawArrow && (m_highlight || active) && drawArrow) + { + TQStyle::PrimitiveElement e = TQStyle::PE_ArrowUp; + int arrowSize = style().pixelMetric(TQStyle::PM_MenuButtonIndicator); + TQRect r((width() - arrowSize)/2, 0, arrowSize, arrowSize); + + switch (m_arrowDirection) + { + case KPanelExtension::Top: + e = TQStyle::PE_ArrowUp; + break; + case KPanelExtension::Bottom: + e = TQStyle::PE_ArrowDown; + r.moveBy(0, height() - arrowSize); + break; + case KPanelExtension::Right: + e = TQStyle::PE_ArrowRight; + r = TQRect(width() - arrowSize, (height() - arrowSize)/2, arrowSize, arrowSize); + break; + case KPanelExtension::Left: + e = TQStyle::PE_ArrowLeft; + r = TQRect(0, (height() - arrowSize)/2, arrowSize, arrowSize); + break; + case KPanelExtension::Floating: + if (orientation() == Qt::Horizontal) + { + e = TQStyle::PE_ArrowDown; + r.moveBy(0, height() - arrowSize); + } + else if (TQApplication::reverseLayout()) + { + e = TQStyle::PE_ArrowLeft; + r = TQRect(0, (height() - arrowSize)/2, arrowSize, arrowSize); + } + else + { + e = TQStyle::PE_ArrowRight; + r = TQRect(width() - arrowSize, (height() - arrowSize)/2, arrowSize, arrowSize); + } + break; + } + + int flags = TQStyle::Style_Enabled; + if (active) + { + flags |= TQStyle::Style_Down; + } + style().tqdrawPrimitive(e, p, r, colorGroup(), flags); + } +} + +// return the icon size that would be used if the panel were proposed_size +// if proposed_size==-1, use the current panel size instead +int PanelButton::preferredIconSize(int proposed_size) const +{ + // (re)calculates the icon sizes and report true if they have changed. + // Get sizes from icontheme. We assume they are sorted. + TDEIconTheme *ith = TDEGlobal::iconLoader()->theme(); + + if (!ith) + { + return -1; // unknown icon size + } + + TQValueList<int> sizes = ith->querySizes(TDEIcon::Panel); + + int sz = ith->defaultSize(TDEIcon::Panel); + + if (proposed_size < 0) + { + proposed_size = (orientation() == Qt::Horizontal) ? height() : width(); + } + + // determine the upper limit on the size. Normally, this is panelSize, + // but if conserve space is requested, the max button size is used instead. + int upperLimit = proposed_size; + if (proposed_size > KickerLib::maxButtonDim() && + KickerSettings::conserveSpace()) + { + upperLimit = KickerLib::maxButtonDim(); + } + + //kdDebug()<<endl<<endl<<flush; + TQValueListConstIterator<int> i = sizes.constBegin(); + while (i != sizes.constEnd()) + { + if ((*i) + (2 * KickerSettings::iconMargin()) > upperLimit) + { + break; + } + sz = *i; // get the largest size under the limit + ++i; + } + + //kdDebug()<<"Using icon sizes: "<<sz<<" "<<zoom_sz<<endl<<flush; + return sz; +} + +void PanelButton::backedByFile(const TQString& localFilePath) +{ + m_backingFile = localFilePath; + + if (m_backingFile.isEmpty()) + { + return; + } + + // avoid multiple connections + disconnect(KDirWatch::self(), TQT_SIGNAL(deleted(const TQString&)), + this, TQT_SLOT(checkForDeletion(const TQString&))); + + if (!KDirWatch::self()->contains(m_backingFile)) + { + KDirWatch::self()->addFile(m_backingFile); + } + + connect(KDirWatch::self(), TQT_SIGNAL(deleted(const TQString&)), + this, TQT_SLOT(checkForDeletion(const TQString&))); + +} + +void PanelButton::setArrowDirection(KPanelExtension::Position dir) +{ + if (m_arrowDirection != dir) + { + m_arrowDirection = dir; + update(); + } +} + +void PanelButton::loadTiles() +{ + if (m_tileColor.isValid()) + { + setBackgroundOrigin(WidgetOrigin); + m_up = m_down = TQPixmap(); + } + else if (m_tile.isNull()) + { + setBackgroundOrigin(AncestorOrigin); + m_up = m_down = TQPixmap(); + } + else + { + setBackgroundOrigin(WidgetOrigin); + // If only the tiles were named a bit smarter we wouldn't have + // to pass the up or down argument. + m_up = TQPixmap(loadTile(m_tile, size(), "up")); + m_down = TQPixmap(loadTile(m_tile, size(), "down")); + } +} + +void PanelButton::loadIcons() +{ + TDEIconLoader * ldr = TDEGlobal::iconLoader(); + TQString nm = m_iconName; + TDEIcon::States defaultState = isEnabled() ? TDEIcon::DefaultState : + TDEIcon::DisabledState; + if (nm=="kmenu-suse") + { + TQString pth = locate( "data", "kicker/data/kickoff/kmenu_basic.png" ); + if (!pth.isEmpty()) + { + m_icon = TQImage(pth); + m_iconh = TQPixmap(m_icon); + m_iconz = TQPixmap(m_icon); + return; + } + } + else + m_icon = ldr->loadIcon(nm, TDEIcon::Panel, m_size, defaultState, 0L, true); + + if (m_icon.isNull()) + { + nm = defaultIcon(); + m_icon = ldr->loadIcon(nm, TDEIcon::Panel, m_size, defaultState); + } + + if (!isEnabled()) + { + m_iconh = m_icon; + } + else + { + m_iconh = ldr->loadIcon(nm, TDEIcon::Panel, m_size, + TDEIcon::ActiveState, 0L, true); + } + + m_iconz = ldr->loadIcon(nm, TDEIcon::Panel, TDEIcon::SizeHuge, + defaultState, 0L, true ); +} + +// (re)calculates the icon sizes and report true if they have changed. +// (false if we don't know, because theme couldn't be loaded?) +bool PanelButton::calculateIconSize() +{ + int size = preferredIconSize(); + + if (size < 0) + { + // size unknown + return false; + } + + if (m_size != size) + { + // Size has changed, update + m_size = size; + return true; + } + + return false; +} + +void PanelButton::setCenterButtonInContainer(bool center) { + m_centerInContainer = center; +} + +void PanelButton::updateKickerTip(KickerTip::Data& data) +{ + data.message = TQStyleSheet::escape(title()); + data.subtext = TQStyleSheet::escape(TQToolTip::textFor(this)); + data.icon = zoomIcon(); + data.direction = popupDirection(); +} + +bool PanelButton::centerButtonInContainer() +{ + return m_centerInContainer; +} + +// +// PanelPopupButton class +// + +PanelPopupButton::PanelPopupButton(TQWidget *parent, const char *name, bool forceStandardCursor) + : PanelButton(parent, name, forceStandardCursor), + m_popup(0), + m_pressedDuringPopup(false), + m_initialized(false) +{ + connect(this, TQT_SIGNAL(pressed()), TQT_SLOT(slotExecMenu())); +} + +void PanelPopupButton::setPopup(TQWidget *popup) +{ + if (m_popup) + { + m_popup->removeEventFilter(this); + disconnect(m_popup, TQT_SIGNAL(aboutToHide()), this, TQT_SLOT(menuAboutToHide())); + } + + m_popup = popup; + setDrawArrow(m_popup != 0); + + if (m_popup) + { + m_popup->installEventFilter(this); + connect(m_popup, TQT_SIGNAL(aboutToHide()), this, TQT_SLOT(menuAboutToHide())); + } +} + +TQWidget *PanelPopupButton::popup() const +{ + return m_popup; +} + +bool PanelPopupButton::eventFilter(TQObject *, TQEvent *e) +{ + if (e->type() == TQEvent::MouseMove) + { + TQMouseEvent *me = TQT_TQMOUSEEVENT(e); + if (TQT_TQRECT_OBJECT(rect()).contains(mapFromGlobal(me->globalPos())) && + ((me->state() & ControlButton) != 0 || + (me->state() & ShiftButton) != 0)) + { + PanelButton::mouseMoveEvent(me); + return true; + } + } + else if (e->type() == TQEvent::MouseButtonPress || + e->type() == TQEvent::MouseButtonDblClick) + { + TQMouseEvent *me = TQT_TQMOUSEEVENT(e); + if (TQT_TQRECT_OBJECT(rect()).contains(mapFromGlobal(me->globalPos()))) + { + m_pressedDuringPopup = true; + return true; + } + } + else if (e->type() == TQEvent::MouseButtonRelease) + { + TQMouseEvent *me = TQT_TQMOUSEEVENT(e); + if (TQT_TQRECT_OBJECT(rect()).contains(mapFromGlobal(me->globalPos()))) + { + if (m_pressedDuringPopup && m_popup) + { + m_popup->hide(); + } + return true; + } + } + return false; +} + +void PanelPopupButton::showMenu() +{ + if (isDown()) + { + if (m_popup) + { + m_popup->hide(); + } + + setDown(false); + return; + } + + setDown(true); + update(); + slotExecMenu(); +} + +void PanelPopupButton::slotExecMenu() +{ + if (!m_popup) + { + return; + } + + m_pressedDuringPopup = false; + KickerTip::enableTipping(false); + kapp->syncX(); + kapp->processEvents(); + + if (!m_initialized) + { + initPopup(); + } + + m_popup->adjustSize(); + if(dynamic_cast<TQPopupMenu*>(m_popup)) + static_cast<TQPopupMenu*>(m_popup)->exec(KickerLib::popupPosition(popupDirection(), m_popup, this)); + // else.. hmm. some derived class has to fix it. +} + +void PanelPopupButton::menuAboutToHide() +{ + if (!m_popup) + { + return; + } + + if (isDown()) { + setDown(false); + KickerTip::enableTipping(true); + } +} + +void PanelPopupButton::triggerDrag() +{ + if (m_popup) + { + m_popup->hide(); + } + + PanelButton::triggerDrag(); +} + +void PanelPopupButton::setInitialized(bool initialized) +{ + m_initialized = initialized; +} + + + diff --git a/kicker/libkicker/panelbutton.h b/kicker/libkicker/panelbutton.h new file mode 100644 index 000000000..80b26f377 --- /dev/null +++ b/kicker/libkicker/panelbutton.h @@ -0,0 +1,488 @@ +/***************************************************************** + +Copyright (c) 1996-2000 the kicker authors. See file AUTHORS. + +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 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 __panelbutton_h__ +#define __panelbutton_h__ + +#include <algorithm> + +#include <tqbutton.h> + +#include <kpanelapplet.h> +#include <kpanelextension.h> +#include <kurldrag.h> + +#include "kickertip.h" + +class TQPopupMenu; +class TDEConfigGroup; +class KShadowEngine; + +/** + * PanelButton is the base class for all buttons to be + * placed in Kicker's panels. It inherits TQButton, and + * KickerTip::Client. + */ +class KDE_EXPORT PanelButton: public TQButton, public KickerTip::Client +{ + Q_OBJECT + +public: + /** + * Create a panel button + * @param parent the parent widget + * @param name the widget's name + */ + PanelButton( TQWidget* parent, const char* name, bool forceStandardCursor = FALSE ); + + /** + * Configures this button according to the user's preferences for + * button tiles/colors/etc. This must be called by the container + * embedding the button after consturction and thereafter whenever + * the configuration changes to ensure it remains properly styled. + * Note that it is not used for configuration specific to the subclass. + */ + void configure(); + + /** + * Prompts the button to save it's configuration. Subclass specific + * settings should be saved in this method to the TDEConfigGroup passed in. + */ + virtual void saveConfig(TDEConfigGroup&) const {} + + /** + * Reimplement this to display a properties dialog for your button. + */ + virtual void properties() {} + + /** + * Reimplement this to give Kicker a hint for the width of the button + * given a certain height. + */ + virtual int widthForHeight(int height) const; + + /** + * Reimplement this to give Kicker a hint for the height of the button + * given a certain width. + */ + virtual int heightForWidth(int width) const; + + /** + * @return the button's current icon + */ + virtual const TQPixmap& labelIcon() const; + + /** + * @return the button's zoom icon + */ + virtual const TQPixmap& zoomIcon() const; + + /** + * @return true if this button is valid. + */ + bool isValid() const; + + /** + * Changes the title for the panel button. + * @param t the button's title + */ + void setTitle(const TQString& t); + + /** + * @return the title of the button. + */ + TQString title() const; + + /** + * Changes the name of the panel button's tile, with + * optional color. + * @param tile the button's tile name + * @param color the button's tile color + */ + void setTile(const TQString& tile, const TQColor& color = TQColor()); + + /** + * Set to true to draw an arrow on the button. + */ + void setDrawArrow(bool drawArrow); + + /** + * Used to set the icon for this panel button. + * @param icon the path to the button's icon + */ + void setIcon(const TQString& icon); + + /** + * @return the button's icon + */ + TQString icon() const; + + /** + * @return whether this button has a text label or not + */ + bool hasText() const; + + /** + * Change the button's text label + * @param text text for button's label + */ + void setButtonText(const TQString& text); + + /** + * @return button's text label + */ + TQString buttonText() const; + + /** + * Change the button's text label color + * @param c the new text label color + */ + void setTextColor(const TQColor& c); + + /** + * @return the button's text label color + */ + TQColor textColor() const; + + /** + * Change the button's text scale + * @param p font scale (in percent) + */ + void setFontPercent(double p); + + /** + * @return the button's text scale (in percent) + */ + double fontPercent() const; + + /** + * @return the orientation of the button + */ + Orientation orientation() const; + + /** + * @return the button's popup direction (read from parent KPanelApplet) + */ + KPanelApplet::Direction popupDirection() const; + + /** + * @return global position of the center of the button + */ + TQPoint center() const; + + /** + * Used to load the graphical tile of the button + * @param name path/name of button's tile + * @param size size of the tile + * @param state used if button has multiple states (null by default) + */ + static TQImage loadTile(const TQString& name, const TQSize&, + const TQString& state = TQString::null); + + /** + * Update the contents of the button's KickerTip + * @param data new KickerTip data + */ + void updateKickerTip(KickerTip::Data& data); + + /** + * @return true if the button should be centered in its parent container, false if not + */ + bool centerButtonInContainer(); + +signals: + /** + * Emitted when the button's icon is changed. + */ + void iconChanged(); + + /** + * Emitted to notify parent containers to save config + */ + void requestSave(); + + /** + * Emitted when the button needs to be removed from it's container + * @see KickerSettings::removeButtonsWhenBroken() + */ + void removeme(); + + /** + * Emitted when the button may need to be removed, but that removal depends + * on as-yet-uncertain future events and therefore ought to be hidden from + * view, though not deleted quite yet. + * @see KickerSettings::removeButtonsWhenBroken() + */ + void hideme(bool hide); + + /** + * Emitted when button initiates a drag + */ + void dragme(const TQPixmap); + + /** + * Overloads dragme to support panel button's with a list of KURL's ([url/servicemenu/browser]button) + */ + void dragme(const KURL::List, const TQPixmap); + +public slots: + /** + * Set to true to enable the button. + */ + void setEnabled(bool enable); + + /** + * Sets the orientation of the button (ie. which direction the icon will rotate). + */ + void setOrientation(Orientation o); + + /** + * Sets the direction to pop up the contents of the button. + */ + virtual void setPopupDirection(KPanelApplet::Direction d); + +protected: + + void setIconAlignment(TQ_Alignment align); + /** + * Subclasses must implement this to define the name of the button which is + * used to identify this button for saving and loading. It must be unique + * to the subclass, should not be i18n'd and is never made user visible. + * KDE4: remove this and use the classname directly instead. + */ + virtual TQString tileName() = 0; + + /** + * @return the default icon for the button + */ + virtual TQString defaultIcon() const { return "unknown"; }; + + /** + * Called right before drag occurs. + */ + virtual void triggerDrag(); + + /** + * Emits a signal to drag the button. Reimplement this if, for example, + * if you need the button to call dragme(KURL::List, const TQPixmap) + * instead of dragme(const TQPixmap) + */ + virtual void startDrag(); + + virtual void enterEvent(TQEvent *); + virtual void leaveEvent(TQEvent *); + virtual void dragEnterEvent(TQDragEnterEvent *); + virtual void dragLeaveEvent(TQDragLeaveEvent *); + virtual void dropEvent(TQDropEvent *); + virtual void mouseMoveEvent(TQMouseEvent *); + virtual void mousePressEvent(TQMouseEvent *); + virtual void mouseReleaseEvent(TQMouseEvent *); + virtual void resizeEvent(TQResizeEvent*); + virtual void drawButton(TQPainter *); + virtual void drawDeepButton(TQPainter *); + virtual void drawButtonLabel(TQPainter *); + virtual void drawButtonLabel(TQPainter *, int voffset, bool drawArrow); + + /** + * @return the preferred icon size. + */ + virtual int preferredIconSize(int proposed_size = -1) const; + + /** + * @return the preferred dimensions for the button + */ + virtual int preferredDimension(int panelDim) const; + + /** + * if the button represents a local file, it tells PanelButton + * what file that is and it starts to watch it. if the file is + * deleted, it is disabled and then checked for one second later + * to see if has returned (e.g. a reinstall occurred) by calling + * checkForBackingFile(). if that returns false, then the button + * is removed from kicker. + * TODO: implement a heuristic that checks back in intervals for + * the reappearance of the file and returns the button to the panel + */ + virtual bool checkForBackingFile(); + + /** + * Set the file backing this button (See @ref checkForBackingFile()), + * you shouldn't need to use this, currently it's only used in [url/service]button + */ + void backedByFile(const TQString& localFilePath); + + /** + * Sets the button's arrow direction. + * @param dir the arrow direction + */ + void setArrowDirection(KPanelExtension::Position dir); + + /** + * Loads the tiles for the button + */ + void loadTiles(); + + /** + * Loads the icons for the button + */ + void loadIcons(); + + /** + * (Re)Calculate icon sizes and return true if they have changed. + */ + bool calculateIconSize(); + + /** + * @param center true if the button should be centered in its parent container, false if not + */ + void setCenterButtonInContainer(bool center); + + bool m_valid; + TQPixmap m_icon; + +protected slots: + /** + * Called from TDEApplication when global icon settings have changed. + * @param group the new group + */ + void updateIcon(int group); + + /** + * Called from TDEApplication when global settings have changed. + * @param category the settings category, see TDEApplication::SettingsCategory + */ + void updateSettings(int category); + + /** + * Used for backedByFile, to check if the file backing this button + * has been deleted. + * @param path path to backing file + */ + void checkForDeletion(const TQString& path); + + /** + * Called to prepare the button for removal from the Kicker + */ + void scheduleForRemoval(); + +private: + TQPoint m_lastLeftMouseButtonPress; + bool m_isLeftMouseButtonDown; + bool m_drawArrow; + bool m_highlight; + bool m_changeCursorOverItem; + bool m_hasAcceptedDrag; + bool m_centerInContainer; + TQColor m_textColor; + TQColor m_tileColor; + TQString m_buttonText; + TQString m_tile; + TQString m_title; + TQString m_iconName; + TQString m_backingFile; + TQPixmap m_up; + TQPixmap m_down; + TQPixmap m_iconh; // hover + TQPixmap m_iconz; // mouse over + KPanelExtension::Position m_arrowDirection; + KPanelApplet::Direction m_popupDirection; + TQ_Alignment m_iconAlignment; + Orientation m_orientation; + int m_size; + double m_fontPercent; + bool m_forceStandardCursor; + static KShadowEngine* s_textShadowEngine; + + class PanelPopupPrivate; + PanelPopupPrivate* d; +}; + +/** + * Base class for panelbuttons which popup a menu + */ +class KDE_EXPORT PanelPopupButton : public PanelButton +{ + Q_OBJECT + +public: + /** + * Create a panel button that pops up a menu. + * @param parent the parent widget + * @param name the widget's name + */ + PanelPopupButton(TQWidget *parent=0, const char *name=0, bool forceStandardCursor = FALSE); + + /** + * Sets the button's popup menu. + * @param popup the menu to pop up + */ + void setPopup(TQWidget *popup); + + /** + * @return the button's popup menu + */ + TQWidget *popup() const; + + bool eventFilter(TQObject *, TQEvent *); + virtual void showMenu(); + +protected: + /** + * Called each time the button is clicked and the popup + * is displayed. Reimplement for dynamic popup menus. + */ + virtual void initPopup() {}; + + /** + * Called before drag occurs. Reimplement to do any + * necessary setup before the button is dragged. + */ + virtual void triggerDrag(); + + /** + * Marks the menu as initialized. + */ + void setInitialized(bool initialized); + +protected slots: + /** + * Connected to the button's pressed() signal, this is + * the code that actually displays the menu. Reimplement if + * you need to take care of any tasks before the popup is + * displayed (eg. KickerTip) + */ + virtual void slotExecMenu(); + +private slots: + void menuAboutToHide(); + +protected: + TQWidget *m_popup; + bool m_pressedDuringPopup; + bool m_initialized; + + class PanelPopupButtonPrivate; + PanelPopupButtonPrivate* d; +}; + +#endif // __panelbutton_h__ diff --git a/kicker/libkicker/paneldrag.cpp b/kicker/libkicker/paneldrag.cpp new file mode 100644 index 000000000..1fb6b9ce6 --- /dev/null +++ b/kicker/libkicker/paneldrag.cpp @@ -0,0 +1,180 @@ +/***************************************************************** +Copyright (c) 2004 Aaron J. Seigo <[email protected]> + 2004 Stephen Depooter <[email protected]> + +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 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 <sys/types.h> +#include <unistd.h> + +#include <tqbuffer.h> + +#include "paneldrag.h" + +#define PANELDRAG_BUFSIZE sizeof(BaseContainer*) + sizeof(pid_t) + +PanelDrag::PanelDrag(BaseContainer* container, TQWidget* dragSource) + : TQDragObject(dragSource, 0) +{ + pid_t source_pid = getpid(); + + a.resize(PANELDRAG_BUFSIZE); + memcpy(a.data(), &container, sizeof(BaseContainer*)); + memcpy(a.data() + sizeof(BaseContainer*), &source_pid, sizeof(pid_t)); +} + +PanelDrag::~PanelDrag() +{ +} + +bool PanelDrag::decode(const TQMimeSource* e, BaseContainer** container) +{ + TQByteArray a = e->encodedData("application/basecontainerptr"); + + if (a.size() != PANELDRAG_BUFSIZE) + { + return false; + } + + pid_t target_pid = getpid(); + pid_t source_pid; + memcpy(&source_pid, a.data() + sizeof(TQObject*), sizeof(pid_t)); + + if (source_pid == target_pid) + { + memcpy(container, a.data(), sizeof(TQObject*)); + return true; + } + + return false; +} + +bool PanelDrag::canDecode(const TQMimeSource *e) +{ + if (!e->provides("application/basecontainerptr")) + { + return false; + } + + TQByteArray a = e->encodedData("application/basecontainerptr"); + if (a.size() != PANELDRAG_BUFSIZE) + { + return false; + } + +/* pid_t target_pid = getpid(); + pid_t source_pid; + memcpy(&source_pid, a.data() + sizeof(void*), sizeof(pid_t)); + + if (source_pid != target_pid) + { + return true; + } */ + + return true; +} + +TQByteArray PanelDrag::encodedData(const char * mimeType) const +{ + if (TQString("application/basecontainerptr") == mimeType && + a.size() == PANELDRAG_BUFSIZE) + { + return a; + } + + return TQByteArray(); +} + +const char * PanelDrag::format(int i) const +{ + if (i == 0) + { + return "application/basecontainerptr"; + } + + return 0; +} + + +AppletInfoDrag::AppletInfoDrag(const AppletInfo& info, TQWidget *dragSource) + : TQDragObject(dragSource, 0) +{ + TQBuffer buff(a); + buff.open(IO_WriteOnly); + TQDataStream s(&buff); + s << info.desktopFile() << info.configFile() << info.type(); +} + +AppletInfoDrag::~AppletInfoDrag() +{ +} + +const char * AppletInfoDrag::format(int i) const +{ + if (i == 0) + { + return "application/appletinfo"; + } + + return 0; +} + +TQByteArray AppletInfoDrag::encodedData(const char* mimeType) const +{ + if (TQString("application/appletinfo") == mimeType) + { + return a; + } + + return TQByteArray(); +} + +bool AppletInfoDrag::canDecode(const TQMimeSource * e) +{ + if (!e->provides("application/appletinfo")) + { + return false; + } + + return true; +} + +bool AppletInfoDrag::decode(const TQMimeSource* e, AppletInfo& container) +{ + TQByteArray a = e->encodedData("application/appletinfo"); + + if (a.isEmpty()) + { + return false; + } + + TQBuffer buff(a); + buff.open(IO_ReadOnly); + TQDataStream s(&buff); + + TQString desktopFile; + TQString configFile; + int type; + s >> desktopFile >> configFile >> type; + AppletInfo info(desktopFile, configFile, (AppletInfo::AppletType)type); + container = info; + return true; +} + diff --git a/kicker/libkicker/paneldrag.h b/kicker/libkicker/paneldrag.h new file mode 100644 index 000000000..6684c32c6 --- /dev/null +++ b/kicker/libkicker/paneldrag.h @@ -0,0 +1,68 @@ +/***************************************************************** +Copyright (c) 2004 Aaron J. Seigo <[email protected]> + 2004 Stephen Depooter <[email protected]> + +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 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 _paneldrag_h_ +#define _paneldrag_h_ + +#include <tqdragobject.h> + +#include <kdemacros.h> + +#include "appletinfo.h" + +class BaseContainer; + +class KDE_EXPORT PanelDrag : public TQDragObject +{ + public: + PanelDrag(BaseContainer* container, TQWidget *dragSource); + ~PanelDrag(); + + virtual const char * format(int i = 0) const; + virtual TQByteArray encodedData(const char *) const; + + static bool canDecode(const TQMimeSource * e); + static bool decode(const TQMimeSource* e, BaseContainer** container); + + private: + TQByteArray a; +}; + +class KDE_EXPORT AppletInfoDrag : public TQDragObject +{ + public: + AppletInfoDrag(const AppletInfo& container, TQWidget *dragSource); + ~AppletInfoDrag(); + + virtual const char * format(int i = 0) const; + virtual TQByteArray encodedData(const char *) const; + + static bool canDecode(const TQMimeSource * e); + static bool decode(const TQMimeSource* e, AppletInfo& container); + + private: + TQByteArray a; +}; + +#endif + diff --git a/kicker/libkicker/panner.cpp b/kicker/libkicker/panner.cpp new file mode 100644 index 000000000..ec06b30c9 --- /dev/null +++ b/kicker/libkicker/panner.cpp @@ -0,0 +1,396 @@ +/***************************************************************** + +Copyright (c) 1996-2000 the kicker authors. See file AUTHORS. + +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 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 <tqlayout.h> +#include <tqtooltip.h> +#include <tqtimer.h> +#include <tqpainter.h> +#include <tqstyle.h> + +#include <tdeglobal.h> +#include <tdelocale.h> +#include <kdebug.h> + +#include "simplebutton.h" +#include "panner.h" +#include "panner.moc" + +Panner::Panner( TQWidget* parent, const char* name ) + : TQWidget( parent, name ), + _luSB(0), + _rdSB(0), + _cwidth(0), _cheight(0), + _cx(0), _cy(0) +{ + TDEGlobal::locale()->insertCatalogue("libkicker"); + setBackgroundOrigin( AncestorOrigin ); + + _updateScrollButtonsTimer = new TQTimer(this); + connect(_updateScrollButtonsTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(reallyUpdateScrollButtons())); + + _clipper = new TQWidget(this); + _clipper->setBackgroundOrigin(AncestorOrigin); + _clipper->installEventFilter( this ); + _viewport = new TQWidget(_clipper); + _viewport->setBackgroundOrigin(AncestorOrigin); + + // layout + _layout = new TQBoxLayout(this, TQBoxLayout::LeftToRight); + _layout->addWidget(_clipper, 1); + setOrientation(Qt::Horizontal); +} + +Panner::~Panner() +{ +} + +void Panner::createScrollButtons() +{ + if (_luSB) + { + return; + } + + // left/up scroll button + _luSB = new SimpleArrowButton(this); + _luSB->installEventFilter(this); + //_luSB->setAutoRepeat(true); + _luSB->setMinimumSize(12, 12); + _luSB->hide(); + _layout->addWidget(_luSB); + connect(_luSB, TQT_SIGNAL(pressed()), TQT_SLOT(startScrollLeftUp())); + connect(_luSB, TQT_SIGNAL(released()), TQT_SLOT(stopScroll())); + + // right/down scroll button + _rdSB = new SimpleArrowButton(this); + _rdSB->installEventFilter(this); + //_rdSB->setAutoRepeat(true); + _rdSB->setMinimumSize(12, 12); + _rdSB->hide(); + _layout->addWidget(_rdSB); + connect(_rdSB, TQT_SIGNAL(pressed()), TQT_SLOT(startScrollRightDown())); + connect(_rdSB, TQT_SIGNAL(released()), TQT_SLOT(stopScroll())); + + // set up the buttons + setupButtons(); +} + +void Panner::setupButtons() +{ + if (orientation() == Qt::Horizontal) + { + if (_luSB) + { + _luSB->setArrowType(Qt::LeftArrow); + _rdSB->setArrowType(Qt::RightArrow); + _luSB->setSizePolicy(TQSizePolicy(TQSizePolicy::Minimum, TQSizePolicy::Expanding)); + _rdSB->setSizePolicy(TQSizePolicy(TQSizePolicy::Minimum, TQSizePolicy::Expanding)); + TQToolTip::add(_luSB, i18n("Scroll left")); + TQToolTip::add(_rdSB, i18n("Scroll right")); + setMinimumSize(24, 0); + } + _layout->setDirection(TQBoxLayout::LeftToRight); + } + else + { + if (_luSB) + { + _luSB->setArrowType(Qt::UpArrow); + _rdSB->setArrowType(Qt::DownArrow); + _luSB->setSizePolicy(TQSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Minimum)); + _rdSB->setSizePolicy(TQSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Minimum)); + TQToolTip::add(_luSB, i18n("Scroll up")); + TQToolTip::add(_rdSB, i18n("Scroll down")); + setMinimumSize(0, 24); + } + _layout->setDirection(TQBoxLayout::TopToBottom); + } + + if (isVisible()) + { + // we need to manually redo the layout if we are visible + // otherwise let the toolkit decide when to do this + _layout->activate(); + } +} + +void Panner::setOrientation(Orientation o) +{ + _orient = o; + setupButtons(); + reallyUpdateScrollButtons(); +} + +void Panner::resizeEvent( TQResizeEvent* ) +{ + //TQScrollView::resizeEvent( e ); + //updateScrollButtons(); +} + +void Panner::scrollRightDown() +{ + if(orientation() == Qt::Horizontal) // scroll right + scrollBy( _step, 0 ); + else // scroll down + scrollBy( 0, _step ); + if (_step < 64) + _step++; +} + +void Panner::scrollLeftUp() +{ + if(orientation() == Qt::Horizontal) // scroll left + scrollBy( -_step, 0 ); + else // scroll up + scrollBy( 0, -_step ); + if (_step < 64) + _step++; +} + +void Panner::startScrollRightDown() +{ + _scrollTimer = new TQTimer(this); + connect(_scrollTimer, TQT_SIGNAL(timeout()), TQT_SLOT(scrollRightDown())); + _scrollTimer->start(50); + _step = 8; + scrollRightDown(); +} + +void Panner::startScrollLeftUp() +{ + _scrollTimer = new TQTimer(this); + connect(_scrollTimer, TQT_SIGNAL(timeout()), TQT_SLOT(scrollLeftUp())); + _scrollTimer->start(50); + _step = 8; + scrollLeftUp(); +} + +void Panner::stopScroll() +{ + delete _scrollTimer; + _scrollTimer = 0; +} + +void Panner::reallyUpdateScrollButtons() +{ + int delta = 0; + + _updateScrollButtonsTimer->stop(); + + if (orientation() == Qt::Horizontal) + { + delta = contentsWidth() - width(); + } + else + { + delta = contentsHeight() - height(); + } + + if (delta >= 1) + { + createScrollButtons(); + + // since the buttons may be visible but of the wrong size + // we need to do this every single time + _luSB->show(); + _rdSB->show(); + } + else if (_luSB && _luSB->isVisibleTo(this)) + { + _luSB->hide(); + _rdSB->hide(); + } +} + +void Panner::updateScrollButtons() +{ + _updateScrollButtonsTimer->start(200, true); +} + +void Panner::setContentsPos(int x, int y) +{ + if (x < 0) + x = 0; + else if (x > (contentsWidth() - visibleWidth())) + x = contentsWidth() - visibleWidth(); + + if (y < 0) + y = 0; + else if (y > (contentsHeight() - visibleHeight())) + y = contentsHeight() - visibleHeight(); + + if (x == contentsX() && y == contentsY()) + return; + + _viewport->move(-x, -y); + emit contentsMoving(x, y); +} + +void Panner::scrollBy(int dx, int dy) +{ + setContentsPos(contentsX() + dx, contentsY() + dy); +} + +void Panner::resizeContents( int w, int h ) +{ + _viewport->resize(w, h); + setContentsPos(contentsX(), contentsY()); + updateScrollButtons(); +} + +TQPoint Panner::contentsToViewport( const TQPoint& p ) const +{ + return TQPoint(p.x() - contentsX() - _clipper->x(), p.y() - contentsY() - _clipper->y()); +} + +TQPoint Panner::viewportToContents( const TQPoint& vp ) const +{ + return TQPoint(vp.x() + contentsX() + _clipper->x(), vp.y() + contentsY() + _clipper->y()); +} + +void Panner::contentsToViewport( int x, int y, int& vx, int& vy ) const +{ + const TQPoint v = contentsToViewport(TQPoint(x,y)); + vx = v.x(); + vy = v.y(); +} + +void Panner::viewportToContents( int vx, int vy, int& x, int& y ) const +{ + const TQPoint c = viewportToContents(TQPoint(vx,vy)); + x = c.x(); + y = c.y(); +} + +void Panner::ensureVisible( int x, int y ) +{ + ensureVisible(x, y, 50, 50); +} + +void Panner::ensureVisible( int x, int y, int xmargin, int ymargin ) +{ + int pw=visibleWidth(); + int ph=visibleHeight(); + + int cx=-contentsX(); + int cy=-contentsY(); + int cw=contentsWidth(); + int ch=contentsHeight(); + + if ( pw < xmargin*2 ) + xmargin=pw/2; + if ( ph < ymargin*2 ) + ymargin=ph/2; + + if ( cw <= pw ) { + xmargin=0; + cx=0; + } + if ( ch <= ph ) { + ymargin=0; + cy=0; + } + + if ( x < -cx+xmargin ) + cx = -x+xmargin; + else if ( x >= -cx+pw-xmargin ) + cx = -x+pw-xmargin; + + if ( y < -cy+ymargin ) + cy = -y+ymargin; + else if ( y >= -cy+ph-ymargin ) + cy = -y+ph-ymargin; + + if ( cx > 0 ) + cx=0; + else if ( cx < pw-cw && cw>pw ) + cx=pw-cw; + + if ( cy > 0 ) + cy=0; + else if ( cy < ph-ch && ch>ph ) + cy=ph-ch; + + setContentsPos( -cx, -cy ); +} + +bool Panner::eventFilter( TQObject *obj, TQEvent *e ) +{ + if ( TQT_BASE_OBJECT(obj) == TQT_BASE_OBJECT(_viewport) || TQT_BASE_OBJECT(obj) == TQT_BASE_OBJECT(_clipper) ) + { + switch ( e->type() ) + { + case TQEvent::Resize: + viewportResizeEvent((TQResizeEvent *)e); + break; + case TQEvent::MouseButtonPress: + viewportMousePressEvent( (TQMouseEvent*)e ); + if ( ((TQMouseEvent*)e)->isAccepted() ) + return true; + break; + case TQEvent::MouseButtonRelease: + viewportMouseReleaseEvent( (TQMouseEvent*)e ); + if ( ((TQMouseEvent*)e)->isAccepted() ) + return true; + break; + case TQEvent::MouseButtonDblClick: + viewportMouseDoubleClickEvent( (TQMouseEvent*)e ); + if ( ((TQMouseEvent*)e)->isAccepted() ) + return true; + break; + case TQEvent::MouseMove: + viewportMouseMoveEvent( (TQMouseEvent*)e ); + if ( ((TQMouseEvent*)e)->isAccepted() ) + return true; + break; + default: + break; + } + } + + return TQWidget::eventFilter( obj, e ); // always continue with standard event processing +} + +void Panner::viewportResizeEvent( TQResizeEvent* ) +{ +} + +void Panner::viewportMousePressEvent( TQMouseEvent* e) +{ + e->ignore(); +} + +void Panner::viewportMouseReleaseEvent( TQMouseEvent* e ) +{ + e->ignore(); +} + +void Panner::viewportMouseDoubleClickEvent( TQMouseEvent* e ) +{ + e->ignore(); +} + +void Panner::viewportMouseMoveEvent( TQMouseEvent* e ) +{ + e->ignore(); +} diff --git a/kicker/libkicker/panner.h b/kicker/libkicker/panner.h new file mode 100644 index 000000000..7ae68d096 --- /dev/null +++ b/kicker/libkicker/panner.h @@ -0,0 +1,115 @@ +/***************************************************************** + +Copyright (c) 1996-2000 the kicker authors. See file AUTHORS. + +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 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 __panner_h__ +#define __panner_h__ + +#include <tqwidget.h> + +#include "simplebutton.h" + +class TQBoxLayout; +class TQTimer; + +class KDE_EXPORT Panner : public TQWidget +{ + Q_OBJECT + +public: + Panner( TQWidget* parent, const char* name = 0 ); + ~Panner(); + + TQSize minimumSizeHint() const { return TQWidget::minimumSizeHint(); } + + Qt::Orientation orientation() const { return _orient; } + virtual void setOrientation(Qt::Orientation orientation); + + TQWidget *viewport() const { return _viewport; } + + TQRect contentsRect() const { return TQRect(0, 0, width(), height()); } + + int contentsX() const { return _viewport ? -_viewport->x() : 0; } + int contentsY() const { return _viewport ? -_viewport->y() : 0; } + int contentsWidth() const { return _viewport ? _viewport->width() : 0; } + int contentsHeight() const { return _viewport ? _viewport->height() : 0; } + void setContentsPos(int x, int y); + + int visibleWidth() const { return _clipper->width(); } + int visibleHeight() const { return _clipper->height(); } + + void contentsToViewport( int x, int y, int& vx, int& vy ) const; + void viewportToContents( int vx, int vy, int& x, int& y ) const; + TQPoint contentsToViewport( const TQPoint& ) const; + TQPoint viewportToContents( const TQPoint& ) const; + + void addChild(TQWidget *child) { child->show(); } + void removeChild(TQWidget *child) { child->hide(); } + int childX(TQWidget *child) const { return child->x(); } + int childY(TQWidget *child) const { return child->y(); } + void moveChild(TQWidget *child, int x, int y) { child->move(x, y); } + + void ensureVisible( int x, int y ); + void ensureVisible( int x, int y, int xmargin, int ymargin ); + +public slots: + virtual void resizeContents( int w, int h ); + void startScrollRightDown(); + void startScrollLeftUp(); + void stopScroll(); + void scrollRightDown(); + void scrollLeftUp(); + void reallyUpdateScrollButtons(); + void scrollBy(int dx, int dy); + +signals: + void contentsMoving(int x, int y); + +protected: + virtual bool eventFilter( TQObject *obj, TQEvent *e ); + virtual void resizeEvent(TQResizeEvent *ev); + virtual void viewportResizeEvent( TQResizeEvent* ); + virtual void viewportMousePressEvent( TQMouseEvent* ); + virtual void viewportMouseReleaseEvent( TQMouseEvent* ); + virtual void viewportMouseDoubleClickEvent( TQMouseEvent* ); + virtual void viewportMouseMoveEvent( TQMouseEvent* ); + +private: + void setupButtons(); + void createScrollButtons(); + void updateScrollButtons(); + + Orientation _orient; + TQBoxLayout *_layout; + SimpleArrowButton *_luSB; // Left Scroll Button + SimpleArrowButton *_rdSB; // Right Scroll Button + TQTimer *_updateScrollButtonsTimer; + TQTimer *_scrollTimer; + + TQWidget *_clipper; + TQWidget *_viewport; + int _cwidth, _cheight; + int _cx, _cy; + int _step; +}; + +#endif diff --git a/kicker/libkicker/simplebutton.cpp b/kicker/libkicker/simplebutton.cpp new file mode 100644 index 000000000..67c90b81a --- /dev/null +++ b/kicker/libkicker/simplebutton.cpp @@ -0,0 +1,289 @@ +/* This file is part of the KDE project + Copyright (C) 2003-2004 Nadeem Hasan <[email protected]> + Copyright (C) 2004-2005 Aaron J. Seigo <[email protected]> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "simplebutton.h" + +#include <tqpainter.h> +#include <tqstyle.h> + +#include <tdeapplication.h> +#include <kcursor.h> +#include <kdialog.h> +#include <tdeglobalsettings.h> +#include <kiconeffect.h> +#include <kicontheme.h> +#include <kipc.h> +#include <kstandarddirs.h> + +#include "kickerSettings.h" + +#define BUTTON_MARGIN KDialog::spacingHint() + +// For now link these two +#define m_disableHighlighting m_forceStandardCursor + +SimpleButton::SimpleButton(TQWidget *parent, const char *name, bool forceStandardCursor) + : TQButton(parent, name), + m_highlight(false), + m_orientation(Qt::Horizontal), + m_forceStandardCursor(forceStandardCursor) +{ + setBackgroundOrigin( AncestorOrigin ); + + connect( kapp, TQT_SIGNAL( settingsChanged( int ) ), + TQT_SLOT( slotSettingsChanged( int ) ) ); + connect( kapp, TQT_SIGNAL( iconChanged( int ) ), + TQT_SLOT( slotIconChanged( int ) ) ); + + kapp->addKipcEventMask( KIPC::SettingsChanged ); + kapp->addKipcEventMask( KIPC::IconChanged ); + + slotSettingsChanged( TDEApplication::SETTINGS_MOUSE ); +} + +void SimpleButton::setPixmap(const TQPixmap &pix) +{ + TQButton::setPixmap(pix); + generateIcons(); + update(); +} + +void SimpleButton::setOrientation(Qt::Orientation orientation) +{ + m_orientation = orientation; + update(); +} + +TQSize SimpleButton::sizeHint() const +{ + const TQPixmap* pm = pixmap(); + + if (!pm) + return TQButton::sizeHint(); + else + return TQSize(pm->width() + BUTTON_MARGIN, pm->height() + BUTTON_MARGIN); +} + +TQSize SimpleButton::minimumSizeHint() const +{ + const TQPixmap* pm = pixmap(); + + if (!pm) + return TQButton::minimumSizeHint(); + else + return TQSize(pm->width(), pm->height()); +} + +void SimpleButton::drawButton( TQPainter *p ) +{ + TQRect r(0, 0, width(), height()); + + if (m_disableHighlighting == TRUE) { + if (m_highlight || isDown() || isOn()) { + int flags = TQStyle::Style_Default | TQStyle::Style_Enabled; + if (isDown() || isOn()) flags |= TQStyle::Style_Down; + style().tqdrawPrimitive(TQStyle::PE_ButtonTool, p, r, colorGroup(), flags); + } + } + + drawButtonLabel(p); +} + +void SimpleButton::drawButtonLabel( TQPainter *p ) +{ + if (!pixmap()) + { + return; + } + + TQPixmap pix = isEnabled() ? ((m_highlight&&(!m_disableHighlighting))? m_activeIcon : m_normalIcon) : m_disabledIcon; + + if ((isOn() || isDown()) && (m_disableHighlighting == FALSE)) + { + pix = TQImage(pix.convertToImage()).smoothScale(pix.width() - 2, + pix.height() - 2); + } + + if (m_disableHighlighting == TRUE) { + pix = TQImage(pix.convertToImage()).smoothScale(pix.width() - 4, + pix.height() - 4); + } + + int h = height(); + int w = width(); + int ph = pix.height(); + int pw = pix.width(); + int margin = BUTTON_MARGIN; + TQPoint origin(margin / 2, margin / 2); + + if (ph < (h - margin)) + { + origin.setY((h - ph) / 2); + } + + if (pw < (w - margin)) + { + origin.setX((w - pw) / 2); + } + + p->drawPixmap(origin, pix); +} + +void SimpleButton::generateIcons() +{ + if (!pixmap()) + { + return; + } + + TQImage image = pixmap()->convertToImage(); + TDEIconEffect effect; + + m_normalIcon = effect.apply(image, TDEIcon::Panel, TDEIcon::DefaultState); + m_activeIcon = effect.apply(image, TDEIcon::Panel, TDEIcon::ActiveState); + m_disabledIcon = effect.apply(image, TDEIcon::Panel, TDEIcon::DisabledState); + + updateGeometry(); +} + +void SimpleButton::slotSettingsChanged(int category) +{ + if (category != TDEApplication::SETTINGS_MOUSE) + { + return; + } + + bool changeCursor; + if (m_forceStandardCursor == FALSE) + changeCursor = TDEGlobalSettings::changeCursorOverIcon(); + else + changeCursor = FALSE; + + if (changeCursor) + { + setCursor(KCursor::handCursor()); + } + else + { + unsetCursor(); + } +} + +void SimpleButton::slotIconChanged( int group ) +{ + if (group != TDEIcon::Panel) + { + return; + } + + generateIcons(); + update(); +} + +void SimpleButton::enterEvent( TQEvent *e ) +{ + if (KickerSettings::showMouseOverEffects()) + m_highlight = true; + + repaint( false ); + TQButton::enterEvent( e ); +} + +void SimpleButton::leaveEvent( TQEvent *e ) +{ + m_highlight = false; + + repaint( false ); + TQButton::enterEvent( e ); +} + +void SimpleButton::resizeEvent( TQResizeEvent * ) +{ + generateIcons(); +} + + +SimpleArrowButton::SimpleArrowButton(TQWidget *parent, Qt::ArrowType arrow, const char *name, bool forceStandardCursor) + : SimpleButton(parent, name, forceStandardCursor), + m_forceStandardCursor(forceStandardCursor) +{ + setBackgroundOrigin(AncestorOrigin); + _arrow = arrow; + _inside = false; +} + +TQSize SimpleArrowButton::sizeHint() const +{ + return TQSize( 12, 12 ); +} + +void SimpleArrowButton::setArrowType(Qt::ArrowType a) +{ + if (_arrow != a) + { + _arrow = a; + update(); + } +} + +Qt::ArrowType SimpleArrowButton::arrowType() const +{ + return _arrow; +} + +void SimpleArrowButton::drawButton( TQPainter *p ) +{ + TQRect r(1, 1, width() - 2, height() - 2); + + TQStyle::PrimitiveElement pe = TQStyle::PE_ArrowLeft; + switch (_arrow) + { + case Qt::LeftArrow: pe = TQStyle::PE_ArrowLeft; break; + case Qt::RightArrow: pe = TQStyle::PE_ArrowRight; break; + case Qt::UpArrow: pe = TQStyle::PE_ArrowUp; break; + case Qt::DownArrow: pe = TQStyle::PE_ArrowDown; break; + } + + int flags = TQStyle::Style_Default | TQStyle::Style_Enabled; + if (isDown() || isOn()) flags |= TQStyle::Style_Down; + style().tqdrawPrimitive(pe, p, r, colorGroup(), flags); + + if (m_forceStandardCursor) { + SimpleButton::drawButton(p); + } +} + +void SimpleArrowButton::enterEvent( TQEvent *e ) +{ + _inside = true; + SimpleButton::enterEvent( e ); + update(); +} + +void SimpleArrowButton::leaveEvent( TQEvent *e ) +{ + _inside = false; + SimpleButton::leaveEvent( e ); + update(); +} + +#include "simplebutton.moc" + +// vim:ts=4:sw=4:et diff --git a/kicker/libkicker/simplebutton.h b/kicker/libkicker/simplebutton.h new file mode 100644 index 000000000..bbfcbd79d --- /dev/null +++ b/kicker/libkicker/simplebutton.h @@ -0,0 +1,91 @@ +/* This file is part of the KDE project + Copyright (C) 2003-2004 Nadeem Hasan <[email protected]> + Copyright (C) 2004-2005 Aaron J. Seigo <[email protected]> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef SIMPLEBUTTON_H +#define SIMPLEBUTTON_H + +#include <tqbutton.h> +#include <tqpixmap.h> + +#include <kdemacros.h> + +class KDE_EXPORT SimpleButton : public TQButton +{ + Q_OBJECT + + public: + SimpleButton(TQWidget *parent, const char *name = 0, bool forceStandardCursor = FALSE); + void setPixmap(const TQPixmap &pix); + void setOrientation(Qt::Orientation orientaton); + TQSize sizeHint() const; + TQSize minimumSizeHint() const; + + protected: + void drawButton( TQPainter *p ); + void drawButtonLabel( TQPainter *p ); + void generateIcons(); + + void enterEvent( TQEvent *e ); + void leaveEvent( TQEvent *e ); + void resizeEvent( TQResizeEvent *e ); + + protected slots: + virtual void slotSettingsChanged( int category ); + virtual void slotIconChanged( int group ); + + private: + bool m_highlight; + TQPixmap m_normalIcon; + TQPixmap m_activeIcon; + TQPixmap m_disabledIcon; + Qt::Orientation m_orientation; + bool m_forceStandardCursor; + class SimpleButtonPrivate; + SimpleButtonPrivate* d; +}; + +class KDE_EXPORT SimpleArrowButton: public SimpleButton +{ + Q_OBJECT + + public: + SimpleArrowButton(TQWidget *parent = 0, Qt::ArrowType arrow = Qt::UpArrow, const char *name = 0, bool forceStandardCursor = FALSE); + virtual ~SimpleArrowButton() {}; + TQSize sizeHint() const; + + protected: + virtual void enterEvent( TQEvent *e ); + virtual void leaveEvent( TQEvent *e ); + virtual void drawButton(TQPainter *p); + Qt::ArrowType arrowType() const; + + public slots: + void setArrowType(Qt::ArrowType a); + + private: + Qt::ArrowType _arrow; + bool m_forceStandardCursor; + bool _inside; +}; + + +#endif // HIDEBUTTON_H + +// vim:ts=4:sw=4:et |