You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tde-style-ia-ora/src/kwin/iaorabutton.cpp

529 lines
17 KiB

/* IaOra KWin window decoration
Copyright (C) 2006 Laurent Montel <lmontel@mandriva.com>
based on plastik code
Copyright (C) 2003-2005 Sandro Giessl <sandro@giessl.com>
based on the window decoration "Web":
Copyright (C) 2001 Rik Hemsley (rikkus) <rik@kde.org>
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 <qbitmap.h>
#include <qpainter.h>
#include <qpixmap.h>
#include <kpixmap.h>
#include <kpixmapeffect.h>
#include <qtimer.h>
#include "iaorabutton.h"
#include "iaorabutton.moc"
#include "iaoraclient.h"
#include "misc.h"
namespace KWinIaOra
{
IaOraButton::IaOraButton(ButtonType type, IaOraClient *parent, const char *name)
: KCommonDecorationButton(type, parent, name),
m_client(parent),
m_iconType(NumButtonIcons),
hover(false)
{
setBackgroundMode(NoBackground);
}
IaOraButton::~IaOraButton()
{
}
void IaOraButton::reset(unsigned long changed)
{
if (changed&DecorationReset || changed&ManualReset || changed&SizeChange || changed&StateChange) {
switch (type() ) {
case CloseButton:
m_iconType = CloseIcon;
break;
case HelpButton:
m_iconType = HelpIcon;
break;
case MinButton:
m_iconType = MinIcon;
break;
case MaxButton:
if (isOn()) {
m_iconType = MaxRestoreIcon;
} else {
m_iconType = MaxIcon;
}
break;
case OnAllDesktopsButton:
if (isOn()) {
m_iconType = NotOnAllDesktopsIcon;
} else {
m_iconType = OnAllDesktopsIcon;
}
break;
case ShadeButton:
if (isOn()) {
m_iconType = UnShadeIcon;
} else {
m_iconType = ShadeIcon;
}
break;
case AboveButton:
if (isOn()) {
m_iconType = NoKeepAboveIcon;
} else {
m_iconType = KeepAboveIcon;
}
break;
case BelowButton:
if (isOn()) {
m_iconType = NoKeepBelowIcon;
} else {
m_iconType = KeepBelowIcon;
}
break;
default:
m_iconType = NumButtonIcons; // empty...
break;
}
this->update();
}
}
void IaOraButton::enterEvent(QEvent *e)
{
QButton::enterEvent(e);
hover = true;
repaint(false);
}
void IaOraButton::leaveEvent(QEvent *e)
{
QButton::leaveEvent(e);
hover = false;
repaint(false);
}
void IaOraButton::drawButton(QPainter *painter)
{
QRect r(0,0,width(),height());
bool active = m_client->isActive();
KPixmap tempKPixmap;
QPixmap buffer;
buffer.resize(width(), height());
QPainter bP(&buffer);
// fake the titlebar background
bP.drawTiledPixmap(0, 0, width(), width(), /*define color*/m_client->getTitleBarTile(active) );
if (type() == MenuButton)
{
QPixmap menuIcon(m_client->icon().pixmap( QIconSet::Small, QIconSet::Normal));
if (width() < menuIcon.width() || height() < menuIcon.height() ) {
menuIcon.convertFromImage( menuIcon.convertToImage().smoothScale(width(), height()));
}
bP.drawPixmap((width()-menuIcon.width())/2, (height()-menuIcon.height())/2, menuIcon);
}
else
{
int dX,dY;
const QBitmap &icon = Handler()->buttonBitmap(m_iconType, size(), decoration()->isToolWindow() );
dX = r.x()+(r.width()-icon.width())/2;
dY = r.y()+(r.height()-icon.height())/2;
if (isDown() ) {
dY++;
}
#if 0
if(!isDown() && Handler()->titleShadow() ) {
QColor shadowColor;
if (qGray(Handler()->getColor(TitleFont,active).rgb()) < 100)
shadowColor = QColor(255, 255, 255);
else
shadowColor = QColor(0,0,0);
//bP.setPen(alphaBlendColors(sourfaceTop, shadowColor, 180) );
bP.drawPixmap(dX+1, dY+1, icon);
}
#endif
bP.setPen(Handler()->getColor(TitleFont,hover ? false : active) );
bP.drawPixmap(dX, dY, icon,0,0,icon.width(),icon.height()/2);
bP.setPen(QColor("#CFD7DF") );
bP.drawPixmap(dX, dY+icon.height()/2, icon,0,icon.height()/2,icon.width(),icon.height());
}
bP.end();
painter->drawPixmap(0, 0, buffer);
}
QBitmap IconEngine::icon(ButtonIcon icon, int size)
{
if (size%2 == 0)
--size;
QBitmap bitmap(size,size);
bitmap.fill(Qt::color0);
QPainter p(&bitmap);
p.setPen(Qt::color1);
QRect r = bitmap.rect();
// line widths
int lwTitleBar = 1;
if (r.width() > 16) {
lwTitleBar = 4;
} else if (r.width() > 4) {
lwTitleBar = 2;
}
int lwArrow = 1;
if (r.width() > 16) {
lwArrow = 4;
} else if (r.width() > 7) {
lwArrow = 2;
}
//QColor col1( "#FFFFFF" );
//QColor col2( "#CFD7DF" );
switch(icon) {
case CloseIcon:
{
int lineWidth = 1;
if (r.width() > 16) {
lineWidth = 3;
} else if (r.width() > 4) {
lineWidth = 2;
}
drawObject(p, DiagonalLine, r.x(), r.y(), r.width(), lineWidth);
drawObject(p, CrossDiagonalLine, r.x(), r.bottom(), r.width(), lineWidth);
break;
}
case MaxIcon:
{
int lineWidth2 = 1; // frame
if (r.width() > 16) {
lineWidth2 = 2;
} else if (r.width() > 4) {
lineWidth2 = 1;
}
drawObject(p, HorizontalLine, r.x(), r.top(), r.width(), lwTitleBar);
drawObject(p, HorizontalLine, r.x(), r.bottom()-(lineWidth2-1), r.width(), lineWidth2);
drawObject(p, VerticalLine, r.x(), r.top(), r.height(), lineWidth2);
drawObject(p, VerticalLine, r.right()-(lineWidth2-1), r.top(), r.height(), lineWidth2);
break;
}
case MaxRestoreIcon:
{
int lineWidth2 = 1; // frame
if (r.width() > 16) {
lineWidth2 = 2;
} else if (r.width() > 4) {
lineWidth2 = 1;
}
int margin1, margin2;
margin1 = margin2 = lineWidth2*2;
if (r.width() < 8)
margin1 = 1;
// background window
drawObject(p, HorizontalLine, r.x(), r.top(), r.width()-margin1+1 +3 , lineWidth2);
drawObject(p, HorizontalLine, r.right()-margin2, r.bottom()-(lineWidth2-1)/*-margin1*/, margin2, lineWidth2);
drawObject(p, VerticalLine, r.x(), r.top(), margin2+3, lineWidth2);
drawObject(p, VerticalLine, r.right()-(lineWidth2-1), r.top(), r.height()-margin1+3, lineWidth2);
// foreground window
drawObject(p, HorizontalLine, r.x(), r.top()+margin2, r.width()-margin2, lwTitleBar);
drawObject(p, HorizontalLine, r.x(), r.bottom()-(lineWidth2-1), r.width()-margin2, lineWidth2);
drawObject(p, VerticalLine, r.x(), r.top()+margin2, r.height(), lineWidth2);
drawObject(p, VerticalLine, r.right()-(lineWidth2-1)-margin2, r.top()+margin2, r.height(), lineWidth2);
break;
}
case MinIcon:
{
int posY = r.height()/2-(lwTitleBar-1);
drawObject(p, HorizontalLine, r.x()+1,posY, r.width()-2, lwTitleBar);
//grey 2
//p.setPen( col2 );
p.drawLine(r.x(),posY+1, r.x()+r.width()-1, posY+1);
p.drawLine(r.x()+1, posY+2, r.x()+r.width()-2, posY+2);
break;
}
case HelpIcon:
{
int center = r.x()+r.width()/2 -1;
int side = r.width()/4;
// paint a question mark... code is quite messy, to be cleaned up later...! :o
if (r.width() > 16) {
int lineWidth = 3;
// top bar
drawObject(p, HorizontalLine, center-side+3, r.y(), 2*side-3-1, lineWidth);
// top bar rounding
drawObject(p, CrossDiagonalLine, center-side-1, r.y()+5, 6, lineWidth);
drawObject(p, DiagonalLine, center+side-3, r.y(), 5, lineWidth);
// right bar
drawObject(p, VerticalLine, center+side+2-lineWidth, r.y()+3, r.height()-(2*lineWidth+side+2+1), lineWidth);
// bottom bar
drawObject(p, CrossDiagonalLine, center, r.bottom()-2*lineWidth, side+2, lineWidth);
drawObject(p, HorizontalLine, center, r.bottom()-3*lineWidth+2, lineWidth, lineWidth);
// the dot
drawObject(p, HorizontalLine, center, r.bottom()-(lineWidth-1), lineWidth, lineWidth);
} else if (r.width() > 8) {
int lineWidth = 2;
// top bar
drawObject(p, HorizontalLine, center-(side-1), r.y(), 2*side-1, lineWidth);
// top bar rounding
if (r.width() > 9) {
drawObject(p, CrossDiagonalLine, center-side-1, r.y()+3, 3, lineWidth);
} else {
drawObject(p, CrossDiagonalLine, center-side-1, r.y()+2, 3, lineWidth);
}
drawObject(p, DiagonalLine, center+side-1, r.y(), 3, lineWidth);
// right bar
drawObject(p, VerticalLine, center+side+2-lineWidth, r.y()+2, r.height()-(2*lineWidth+side+1), lineWidth);
// bottom bar
drawObject(p, CrossDiagonalLine, center, r.bottom()-2*lineWidth+1, side+2, lineWidth);
// the dot
drawObject(p, HorizontalLine, center, r.bottom()-(lineWidth-1), lineWidth, lineWidth);
} else {
int lineWidth = 1;
// top bar
drawObject(p, HorizontalLine, center-(side-1), r.y(), 2*side, lineWidth);
// top bar rounding
drawObject(p, CrossDiagonalLine, center-side-1, r.y()+1, 2, lineWidth);
// right bar
drawObject(p, VerticalLine, center+side+1, r.y(), r.height()-(side+2+1), lineWidth);
// bottom bar
drawObject(p, CrossDiagonalLine, center, r.bottom()-2, side+2, lineWidth);
// the dot
drawObject(p, HorizontalLine, center, r.bottom(), 1, 1);
}
break;
}
case NotOnAllDesktopsIcon:
{
int lwMark = r.width()-lwTitleBar*2-2;
if (lwMark < 1)
lwMark = 3;
drawObject(p, HorizontalLine, r.x()+(r.width()-lwMark)/2, r.y()+(r.height()-lwMark)/2, lwMark, lwMark);
// Fall through to OnAllDesktopsIcon intended!
}
case OnAllDesktopsIcon:
{
// horizontal bars
drawObject(p, HorizontalLine, r.x()+lwTitleBar, r.y(), r.width()-2*lwTitleBar, lwTitleBar);
drawObject(p, HorizontalLine, r.x()+lwTitleBar, r.bottom()-(lwTitleBar-1), r.width()-2*lwTitleBar, lwTitleBar);
// vertical bars
drawObject(p, VerticalLine, r.x(), r.y()+lwTitleBar, r.height()-2*lwTitleBar, lwTitleBar);
drawObject(p, VerticalLine, r.right()-(lwTitleBar-1), r.y()+lwTitleBar, r.height()-2*lwTitleBar, lwTitleBar);
break;
}
case NoKeepAboveIcon:
{
int center = r.x()+r.width()/2;
// arrow
drawObject(p, CrossDiagonalLine, r.x(), center+2*lwArrow, center-r.x(), lwArrow);
drawObject(p, DiagonalLine, r.x()+center, r.y()+1+2*lwArrow, center-r.x(), lwArrow);
if (lwArrow>1)
drawObject(p, HorizontalLine, center-(lwArrow-2), r.y()+2*lwArrow, (lwArrow-2)*2, lwArrow);
// Fall through to KeepAboveIcon intended!
}
case KeepAboveIcon:
{
int center = r.x()+r.width()/2;
// arrow
drawObject(p, CrossDiagonalLine, r.x(), center, center-r.x(), lwArrow);
drawObject(p, DiagonalLine, r.x()+center, r.y()+1, center-r.x(), lwArrow);
if (lwArrow>1)
drawObject(p, HorizontalLine, center-(lwArrow-2), r.y(), (lwArrow-2)*2, lwArrow);
break;
}
case NoKeepBelowIcon:
{
int center = r.x()+r.width()/2;
// arrow
drawObject(p, DiagonalLine, r.x(), center-2*lwArrow, center-r.x(), lwArrow);
drawObject(p, CrossDiagonalLine, r.x()+center, r.bottom()-1-2*lwArrow, center-r.x(), lwArrow);
if (lwArrow>1)
drawObject(p, HorizontalLine, center-(lwArrow-2), r.bottom()-(lwArrow-1)-2*lwArrow, (lwArrow-2)*2, lwArrow);
// Fall through to KeepBelowIcon intended!
}
case KeepBelowIcon:
{
int center = r.x()+r.width()/2;
// arrow
drawObject(p, DiagonalLine, r.x(), center, center-r.x(), lwArrow);
drawObject(p, CrossDiagonalLine, r.x()+center, r.bottom()-1, center-r.x(), lwArrow);
if (lwArrow>1)
drawObject(p, HorizontalLine, center-(lwArrow-2), r.bottom()-(lwArrow-1), (lwArrow-2)*2, lwArrow);
break;
}
case ShadeIcon:
{
drawObject(p, HorizontalLine, r.x(), r.y(), r.width(), lwTitleBar);
break;
}
case UnShadeIcon:
{
int lw1 = 1;
int lw2 = 1;
if (r.width() > 16) {
lw1 = 4;
lw2 = 2;
} else if (r.width() > 7) {
lw1 = 2;
lw2 = 1;
}
int h = QMAX( (r.width()/2), (lw1+2*lw2) );
// horizontal bars
drawObject(p, HorizontalLine, r.x(), r.y(), r.width(), lw1);
drawObject(p, HorizontalLine, r.x(), r.x()+h-(lw2-1), r.width(), lw2);
// vertical bars
drawObject(p, VerticalLine, r.x(), r.y(), h, lw2);
drawObject(p, VerticalLine, r.right()-(lw2-1), r.y(), h, lw2);
break;
}
default:
break;
}
p.end();
bitmap.setMask(bitmap);
return bitmap;
}
void IconEngine::drawObject(QPainter &p, Object object, int x, int y, int length, int lineWidth)
{
switch(object) {
case DiagonalLine:
if (lineWidth <= 1) {
for (int i = 0; i < length; ++i) {
p.drawPoint(x+i,y+i);
}
} else if (lineWidth <= 2) {
for (int i = 0; i < length; ++i) {
p.drawPoint(x+i,y+i);
}
for (int i = 0; i < (length-1); ++i) {
p.drawPoint(x+1+i,y+i);
p.drawPoint(x+i,y+1+i);
}
} else {
for (int i = 1; i < (length-1); ++i) {
p.drawPoint(x+i,y+i);
}
for (int i = 0; i < (length-1); ++i) {
p.drawPoint(x+1+i,y+i);
p.drawPoint(x+i,y+1+i);
}
for (int i = 0; i < (length-2); ++i) {
p.drawPoint(x+2+i,y+i);
p.drawPoint(x+i,y+2+i);
}
}
break;
case CrossDiagonalLine:
if (lineWidth <= 1) {
for (int i = 0; i < length; ++i) {
p.drawPoint(x+i,y-i);
}
} else if (lineWidth <= 2) {
for (int i = 0; i < length; ++i) {
p.drawPoint(x+i,y-i);
}
for (int i = 0; i < (length-1); ++i) {
p.drawPoint(x+1+i,y-i);
p.drawPoint(x+i,y-1-i);
}
} else {
for (int i = 1; i < (length-1); ++i) {
p.drawPoint(x+i,y-i);
}
for (int i = 0; i < (length-1); ++i) {
p.drawPoint(x+1+i,y-i);
p.drawPoint(x+i,y-1-i);
}
for (int i = 0; i < (length-2); ++i) {
p.drawPoint(x+2+i,y-i);
p.drawPoint(x+i,y-2-i);
}
}
break;
case HorizontalLine:
for (int i = 0; i < lineWidth; ++i) {
p.drawLine(x,y+i, x+length-1, y+i);
}
break;
case VerticalLine:
for (int i = 0; i < lineWidth; ++i) {
p.drawLine(x+i,y, x+i, y+length-1);
}
break;
default:
break;
}
}
} // KWinIaOra