// // C++ Implementation: malloryclient // // Description: // // // Author: Remi Villatel , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #include #include #include #include #include #include #include #include #include #include #include #include "malloryclient.h" #include "malloryhandler.h" #include "mallorybutton.h" #include "pixmaps.h" #include "enums.h" MalloryClient::MalloryClient(KDecorationBridge *bridge, KDecorationFactory *factory) : KDecoration(bridge, factory), m_titleBar(0) { } MalloryClient::~MalloryClient() { // Delete buttons from memory. for (int n=0; ninstallEventFilter(this); widget()->setBackgroundMode(NoBackground); // to avoid flicker // Set up layout TQGridLayout *mainLayout = new TQGridLayout(widget(), 4, 3); // 4 x 3 grid TQHBoxLayout *titleLayout = new TQHBoxLayout(); TQVBoxLayout *leftButtonLayout = new TQVBoxLayout(); TQHBoxLayout *leftButtonLayout2 = new TQHBoxLayout(); leftButtonLayout->setSpacing(2); TQVBoxLayout *rightButtonLayout = new TQVBoxLayout(); TQHBoxLayout *rightButtonLayout2 = new TQHBoxLayout(); rightButtonLayout->setSpacing(2); mainLayout->setResizeMode(TQLayout::FreeResize); m_titleBar = new TQSpacerItem(1, MalloryHandler::titleSize(), TQSizePolicy::Expanding, TQSizePolicy::Fixed); m_leftSpacer = new TQSpacerItem(1, 1); m_rightSpacer = new TQSpacerItem(1, 1); m_topSpacer = new TQSpacerItem(1, 1); // 2nd argument is the top margin. m_bottomSpacer = new TQSpacerItem(1, MalloryHandler::borderSize()); m_leftButtonSpacer = new TQSpacerItem(MalloryHandler::buttonSpacing(), MalloryHandler::titleSize()); m_rightButtonSpacer = new TQSpacerItem(MalloryHandler::buttonSpacing(), MalloryHandler::titleSize()); m_leftButtonSpacer2 = new TQSpacerItem(1, (MalloryHandler::titleSize()-MalloryHandler::buttonSize())/2, TQSizePolicy::Minimum, TQSizePolicy::Fixed); m_rightButtonSpacer2 = new TQSpacerItem(1, (MalloryHandler::titleSize()-MalloryHandler::buttonSize())/2, TQSizePolicy::Minimum, TQSizePolicy::Fixed); mainLayout->addItem(m_topSpacer, 0, 1); mainLayout->addItem(m_bottomSpacer, 3, 1); mainLayout->addItem(m_leftSpacer, 1, 0); mainLayout->addItem(m_rightSpacer, 1, 2); mainLayout->addLayout(titleLayout, 1, 1); if (isPreview()) { mainLayout->addWidget(new TQLabel(i18n("
Mallory
"), widget()), 2, 1); } else { mainLayout->addItem(new TQSpacerItem(0, 0), 2, 1); } // Make the window stretch mainLayout->setRowStretch(2, 10); mainLayout->setColStretch(1, 10); titleLayout->addLayout(leftButtonLayout); // Contains the left buttons titleLayout->addItem(m_leftButtonSpacer); // Left button margin titleLayout->addItem(m_titleBar); // The text titleLayout->addItem(m_rightButtonSpacer); // Right button margin titleLayout->addLayout(rightButtonLayout); // Contains the right buttons for (int n=0; naddItem(m_leftButtonSpacer2); leftButtonLayout->addLayout(leftButtonLayout2); addButtons(leftButtonLayout2, options()->customButtonPositions() ? options()->titleButtonsLeft() : TQString(default_left)); // Add the right buttons rightButtonLayout->addItem(m_rightButtonSpacer2); rightButtonLayout->addLayout(rightButtonLayout2); addButtons(rightButtonLayout2, options()->customButtonPositions() ? options()->titleButtonsRight() : TQString(default_right)); } bool MalloryClient::eventFilter(TQObject *o, TQEvent *e) { if (o != widget()) return false; switch (e->type()) { case TQEvent::Resize: resizeEvent(static_cast(e)); return true; case TQEvent::Paint: paintEvent(static_cast(e)); return true; case TQEvent::MouseButtonDblClick: mouseDoubleClickEvent(static_cast(e)); return true; case TQEvent::MouseButtonPress: processMousePressEvent(static_cast(e)); return true; case TQEvent::Show: showEvent(static_cast(e)); return true; default: return false; } } void MalloryClient::addButtons(TQBoxLayout *layout, const TQString &s) { if (s.length() > 0) { for (unsigned n=0; naddWidget(m_button[ButtonMenu], 0, TQt::AlignHCenter | TQt::AlignTop); } break; case 'H': // Help if (!m_button[ButtonHelp] && providesContextHelp()) { m_button[ButtonHelp] = new MalloryButton(this, "help", i18n("Help"), ButtonHelp); connect(m_button[ButtonHelp], TQ_SIGNAL(clicked()), this, TQ_SLOT(showContextHelp())); layout->addWidget(m_button[ButtonHelp], 0, TQt::AlignHCenter | TQt::AlignTop); } break; case 'I': // Minimize if ((!m_button[ButtonMin]) && isMinimizable()) { m_button[ButtonMin] = new MalloryButton(this, "minimize", i18n("Minimize"), ButtonMin); connect(m_button[ButtonMin], TQ_SIGNAL(clicked()), this, TQ_SLOT(minimize())); layout->addWidget(m_button[ButtonMin], 0, TQt::AlignHCenter | TQt::AlignTop); } break; case 'A': // Maximize if ((!m_button[ButtonMax]) && isMaximizable()) { m_button[ButtonMax] = new MalloryButton(this, "maximize", (maximizeMode()!=MaximizeRestore)?i18n("Minimize"):i18n("Maximize"), ButtonMax); connect(m_button[ButtonMax], TQ_SIGNAL(clicked()), this, TQ_SLOT(maxButtonPressed())); layout->addWidget(m_button[ButtonMax], 0, TQt::AlignHCenter | TQt::AlignTop); } break; case 'X': // Close if ((!m_button[ButtonClose]) && isCloseable()) { m_button[ButtonClose] = new MalloryButton(this, "close", i18n("Close"), ButtonClose); connect(m_button[ButtonClose], TQ_SIGNAL(clicked()), this, TQ_SLOT(closeWindow())); layout->addWidget(m_button[ButtonClose], 0, TQt::AlignHCenter | TQt::AlignTop); } break; case 'S': // OnAllDesktops if (!m_button[ButtonOnAllDesktops]) { m_button[ButtonOnAllDesktops] = new MalloryButton(this, "onAllDesktops", isOnAllDesktops() ? i18n("Not On All Desktops") : i18n("On All Desktops"), ButtonOnAllDesktops); m_button[ButtonOnAllDesktops]->setOnAllDesktops(isOnAllDesktops()); connect(m_button[ButtonOnAllDesktops], TQ_SIGNAL(clicked()), this, TQ_SLOT(toggleOnAllDesktops())); layout->addWidget(m_button[ButtonOnAllDesktops], 0, TQt::AlignHCenter | TQt::AlignTop); } break; case 'F': // Above all others if (!m_button[ButtonAbove]) { m_button[ButtonAbove] = new MalloryButton(this, "above", i18n("Keep Above Others"), ButtonAbove); connect(m_button[ButtonAbove], TQ_SIGNAL(clicked()), this, TQ_SLOT(slotKeepAbove())); layout->addWidget(m_button[ButtonAbove], 0, TQt::AlignHCenter | TQt::AlignTop); } break; case 'B': // Below all others if (!m_button[ButtonBelow]) { m_button[ButtonBelow] = new MalloryButton(this, "below", i18n("Keep Below Others"), ButtonBelow); connect(m_button[ButtonBelow], TQ_SIGNAL(clicked()), this, TQ_SLOT(slotKeepBelow())); layout->addWidget(m_button[ButtonBelow], 0, TQt::AlignHCenter | TQt::AlignTop); } break; case '_': // Spacer layout->addSpacing(MalloryHandler::buttonSpacing()); } } } } void MalloryClient::paintEvent(TQPaintEvent*) { if (!MalloryHandler::initialized()) return; bool active = isActive(); TQPainter painter(widget()); TQColor cottl = options()->color(ColorTitleBar, active); TQColor coblnd = options()->color(ColorTitleBlend, active); TQColor cofrm = options()->color(ColorFrame, active); TQColor cobttn = options()->color(ColorButtonBg, active); TQColorGroup widgetGroup; widgetGroup = widget()->colorGroup(); TQColor coground = widgetGroup.background(); int cfr, cfg, cfb, alr, alg, alb; cofrm.getRgb(&cfr, &cfg, &cfb); coground.getRgb(&alr, &alg, &alb); TQColor aliasing = tqRgb((cfr+alr)/2, (cfg+alg)/2, (cfb+alb)/2); TQRect titleRect(m_titleBar->geometry()); TQRect topRect(m_topSpacer->geometry()); TQRect leftRect(m_leftSpacer->geometry()); TQRect rightRect(m_rightSpacer->geometry()); TQRect bottomRect(m_bottomSpacer->geometry()); TQFontMetrics fm(options()->font(active, false)); int rr = rightRect.right(); int bb = bottomRect.bottom(); TQRegion mask; if(maximizeMode() != MaximizeFull) { mask = TQRegion(0, 0, rr+1, bb+1); if (MalloryHandler::lessRounded()) { // Remove top left corner mask -= TQRegion(0, 0, 2, 1); mask -= TQRegion(0, 1, 1, 1); // Remove top right corner mask -= TQRegion(rr-1, 0, 2, 1); mask -= TQRegion(rr, 1, 1, 1); // Remove bottom left corner mask -= TQRegion(0, bb, 2, 1); mask -= TQRegion(0, bb-1, 1, 1); // Remove bottom right corner mask -= TQRegion(rr-1, bb, 2, 1); mask -= TQRegion(rr, bb-1, 1, 1); } else { // Remove top left corner mask -= TQRegion(0, 0, 5, 1); mask -= TQRegion(0, 1, 3, 1); mask -= TQRegion(0, 2, 2, 1); mask -= TQRegion(0, 3, 1, 2); // Remove top right corner mask -= TQRegion(rr-4, 0, 5, 1); mask -= TQRegion(rr-2, 1, 3, 1); mask -= TQRegion(rr-1, 2, 2, 1); mask -= TQRegion(rr, 3, 1, 2); // Remove bottom left corner mask -= TQRegion(0, bb, 5, 1); mask -= TQRegion(0, bb-1, 3, 1); mask -= TQRegion(0, bb-2, 2, 1); mask -= TQRegion(0, bb-4, 1, 2); // Remove bottom right corner mask -= TQRegion(rr-4, bb, 5, 1); mask -= TQRegion(rr-2, bb-1, 3, 1); mask -= TQRegion(rr-1, bb-2, 2, 1); mask -= TQRegion(rr, bb-4, 1, 2); } } else { mask = TQRegion(0, 0, rightRect.right()+1, bottomRect.bottom()+1); } setMask(mask); painter.drawTiledPixmap(1, titleRect.top(), topRect.width()+leftRect.width()+rightRect.width()-2, titleRect.bottom()-titleRect.top(), active ? *Pixmaps::active_titlebar : *Pixmaps::inactive_titlebar); if (titleRect.width() > 0) // Do we even have to paint the title? { TQPixmap pufferPixmap; pufferPixmap.resize(titleRect.width(), titleRect.height()-1); int flags = AlignAuto | AlignVCenter; TQPainter pufferPainter(&pufferPixmap); pufferPainter.drawTiledPixmap(pufferPixmap.rect(), active ? *Pixmaps::active_titlebar : *Pixmaps::inactive_titlebar); pufferPainter.setFont(options()->font(active, false)); // Shift the text 2 px to the right. pufferPainter.translate(2, 0); // Draw title shadow when required... if (MalloryHandler::titleShadow()) { pufferPainter.translate(MalloryHandler::titleShadowSize(), MalloryHandler::titleShadowSize()); pufferPainter.setPen(cobttn); // Use button color for the shadow pufferPainter.drawText(pufferPixmap.rect(), flags, caption()); pufferPainter.translate(-(MalloryHandler::titleShadowSize()), -(MalloryHandler::titleShadowSize())); } // Draw title text pufferPainter.setPen(options()->color(ColorFont, active)); pufferPainter.drawText(pufferPixmap.rect(), flags, caption()); pufferPainter.end(); painter.drawPixmap(titleRect.left(), titleRect.top(), pufferPixmap); } // Now we're going to draw the frame... // Fill the borders with the background colour painter.setPen(coground); painter.drawLine(leftRect.left()+1, titleRect.bottom(), rightRect.right()-1, titleRect.bottom()); TQRect frame; // Left frame.setCoords(leftRect.left()+1, titleRect.bottom(), leftRect.right(), bottomRect.bottom()-1); painter.fillRect(frame, coground); // Right frame.setCoords(rightRect.left(), titleRect.bottom(), rightRect.right()-1, bottomRect.bottom()-1); painter.fillRect(frame, coground); // Bottom frame.setCoords(leftRect.right(), bottomRect.top(), rightRect.left(), bottomRect.bottom()-1); painter.fillRect(frame, coground); // External borders painter.setPen(cofrm); // if(maximizeMode() != MaximizeFull) { if (MalloryHandler::lessRounded()) { painter.drawLine(2, 0, rr-2, 0); painter.drawPoint(1, 1); painter.drawPoint(rr-1, 1); // painter.drawLine(0, 2, 0, bb-2); painter.drawLine(rr, 2, rr, bb-2); // painter.drawPoint(1, bb-1); painter.drawPoint(rr-1, bb-1); painter.drawLine(2, bb, rr-2, bb); // painter.setPen(aliasing); // painter.drawLine(2, 1, rr-2, 1); painter.drawPoint(2, 2); painter.drawPoint(rr-2, 2); // painter.drawLine(1, 2, 1, bb-2); painter.drawLine(rr-1, 2, rr-1, bb-2); // painter.drawPoint(2, bb-2); painter.drawPoint(rr-2, bb-2); painter.drawLine(2, bb-1, rr-2, bb-1); } else { painter.drawLine(5, 0, rr-5, 0); painter.drawLine(3, 1, 4, 1); painter.drawLine(rr-3, 1, rr-4, 1); painter.drawPoint(2, 2); painter.drawPoint(rr-2, 2); painter.drawLine(1, 3, 1, 4); painter.drawLine(rr-1, 3, rr-1, 4); // painter.drawLine(0, 5, 0, bb-5); painter.drawLine(rr, 5, rr, bb-5); // painter.drawLine(5, bb, rr-5, bb); painter.drawLine(3, bb-1, 4, bb-1); painter.drawLine(rr-3, bb-1, rr-4, bb-1); painter.drawPoint(2, bb-2); painter.drawPoint(rr-2, bb-2); painter.drawLine(1, bb-3, 1, bb-4); painter.drawLine(rr-1, bb-3, rr-1, bb-4); // painter.setPen(aliasing); // painter.drawLine(5, 1, rr-5, 1); painter.drawLine(3, 2, 5, 2); painter.drawLine(rr-3, 2, rr-5, 2); painter.drawPoint(3, 3); painter.drawPoint(rr-3, 3); painter.drawLine(2, 3, 2, 5); painter.drawLine(rr-2, 3, rr-2, 5); // painter.drawLine(1, 5, 1, bb-5); painter.drawLine(rr-1, 5, rr-1, bb-5); // painter.drawLine(5, bb-1, rr-5, bb-1); painter.drawLine(3, bb-2, 5, bb-2); painter.drawLine(rr-3, bb-2, rr-5, bb-2); painter.drawPoint(3, bb-3); painter.drawPoint(rr-3, bb-3); painter.drawLine(2, bb-3, 2, bb-5); painter.drawLine(rr-2, bb-3, rr-2, bb-5); } } else { // Square/Maximized external borders painter.drawRect(0, 0, rightRect.right()+1, bottomRect.bottom()+1); painter.setPen(aliasing); painter.drawRect(1, 1, rightRect.right()-1, bottomRect.bottom()-1); } // The resize handles when required... if (MalloryHandler::resizeHandle()) { if (isResizable()) { painter.setPen(options()->color(ColorHandle, active)); if (MalloryHandler::lessRounded()) { // Corners painter.drawRect(2, bb-3, 2, 2); painter.drawRect(rr-3, bb-3, 2, 2); if(MalloryHandler::superSize()) { // Above corners painter.drawRect(2, bb-6, 2, 2); painter.drawRect(rr-3, bb-6, 2, 2); // Within bottom painter.drawRect(5, bb-3, 2, 2); painter.drawRect(rr-6, bb-3, 2, 2); } } else { // Above corners painter.drawRect(2, bb-6, 2, 2); painter.drawRect(rr-3, bb-6, 2, 2); // Within bottom painter.drawRect(5, bb-3, 2, 2); painter.drawRect(rr-6, bb-3, 2, 2); if(MalloryHandler::superSize()) { // Above above painter.drawRect(2, bb-8, 2, 2); painter.drawRect(rr-3, bb-8, 2, 2); // Corners painter.drawRect(3, bb-4, 2, 2); painter.drawRect(rr-4, bb-4, 2, 2); // Within within painter.drawRect(7, bb-3, 2, 2); painter.drawRect(rr-8, bb-3, 2, 2); } } } } } void MalloryClient::showEvent(TQShowEvent*) { widget()->update(); } void MalloryClient::resizeEvent(TQResizeEvent*) { if ((widget()->isVisibleToTLW()) && (!widget()->testWFlags(WStaticContents))) { TQRegion region = widget()->rect(); region.subtract(m_titleBar->geometry()); widget()->erase(region); } } void MalloryClient::captionChange() { widget()->repaint(m_titleBar->geometry(), false); } void MalloryClient::mouseDoubleClickEvent(TQMouseEvent *e) { if (m_titleBar->geometry().contains(e->pos())) { titlebarDblClickOperation(); } } MalloryClient::Position MalloryClient::mousePosition(const TQPoint &point) const { const int corner = 24; MalloryClient::Position pos = PositionCenter; // Often needed coordinates... TQRect titleRect(m_titleBar->geometry()); TQRect topRect(m_topSpacer->geometry()); TQRect leftRect(m_leftSpacer->geometry()); TQRect rightRect(m_rightSpacer->geometry()); TQRect bottomRect(m_bottomSpacer->geometry()); if ((m_leftButtonSpacer2->geometry().height() > 0) ? (point.y() <= (m_leftButtonSpacer2->geometry().bottom())) : (point.y() <= topRect.bottom())) { // We're inside the top frame. if (point.x() <= corner) pos = PositionTopLeft; else if (point.x() >= (width()-corner)) pos = PositionTopRight; else pos = PositionTop; } else if (topRect.height() <= 0 && point.y() <= 2) { // We're inside the top frame, probably maximized. if ((point.x() >= titleRect.left()) && (point.x() <= titleRect.left()+corner)) pos = PositionLeft; else if ((point.x() >= titleRect.right()-corner) && (point.x() <= titleRect.right())) pos = PositionTopRight; else if ((point.x() > titleRect.left()) && (point.x() < titleRect.right())) pos = PositionTop; } else if (point.y() >= bottomRect.top()) { // Inside handle if (point.x() <= corner) pos = PositionBottomLeft; else if (point.x() >= (width()-corner)) pos = PositionBottomRight; else pos = PositionBottom; } else if (point.x() <= leftRect.right()) { // Inside the left frame. if (point.y() <= corner) pos = PositionTopLeft; else if (point.y() >= (height()-corner)) pos = PositionBottomLeft; else pos = PositionLeft; } else if (point.x() >= rightRect.left()) { // Inside the right frame. if (point.y() <= corner) pos = PositionTopRight; else if (point.y() >= (height()-corner)) pos = PositionBottomRight; else pos = PositionRight; } else { // Inside the frame somewhere... pos = PositionCenter; } return pos; } void MalloryClient::iconChange() { if (m_button[ButtonMenu]) { m_button[ButtonMenu]->repaint(false); } } void MalloryClient::activeChange() { // Repaint the buttons when state changes for (int n=0; nrepaint(false); widget()->repaint(false); } void MalloryClient::maximizeChange() { const bool m = (maximizeMode() != MaximizeRestore); if (m_button[ButtonMax]) { m_button[ButtonMax]->setMaximized(m); m_button[ButtonMax]->setTipText(m ? i18n("Restore") : i18n("Maximize")); } } void MalloryClient::desktopChange() { if (m_button[ButtonOnAllDesktops]) { m_button[ButtonOnAllDesktops]->setOnAllDesktops(isOnAllDesktops()); m_button[ButtonOnAllDesktops]->setTipText(isOnAllDesktops() ? i18n("Not On All Desktops") : i18n("On All Desktops")); } } void MalloryClient::maxButtonPressed() { if (m_button[ButtonMax]) { switch (m_button[ButtonMax]->lastMousePress()) { case MidButton: maximize(maximizeMode() ^ MaximizeVertical); break; case RightButton: maximize(maximizeMode() ^ MaximizeHorizontal); break; default: maximize(maximizeMode() == MaximizeFull ? MaximizeRestore : MaximizeFull); } } } void MalloryClient::menuButtonPressed() { if (m_button[ButtonMenu]) { TQPoint pt(m_button[ButtonMenu]->rect().bottomLeft().x(), m_button[ButtonMenu]->rect().bottomLeft().y()); showWindowMenu(m_button[ButtonMenu]->mapToGlobal(pt)); m_button[ButtonMenu]->setDown(false); } } TQSize MalloryClient::minimumSize() const { return TQSize(112, 40); } void MalloryClient::borders(int& left, int& right, int& top, int& bottom) const { m_leftSpacer->changeSize(MalloryHandler::borderSize(), 1, TQSizePolicy::Expanding, TQSizePolicy::Minimum ); m_rightSpacer->changeSize(MalloryHandler::borderSize(), 1, TQSizePolicy::Expanding, TQSizePolicy::Minimum ); m_topSpacer->changeSize(1, 1); m_bottomSpacer->changeSize(1, MalloryHandler::borderSize()); m_leftButtonSpacer->changeSize( 3, 1); m_rightButtonSpacer->changeSize( 3, 1); m_titleBar->changeSize(1, MalloryHandler::titleSize(), TQSizePolicy::Expanding, TQSizePolicy::Fixed); m_leftButtonSpacer2->changeSize(1, (MalloryHandler::titleSize()-MalloryHandler::buttonSize())/2, TQSizePolicy::Minimum, TQSizePolicy::Fixed); m_rightButtonSpacer2->changeSize(1, (MalloryHandler::titleSize()-MalloryHandler::buttonSize())/2, TQSizePolicy::Minimum, TQSizePolicy::Fixed); left = right = bottom = MalloryHandler::borderSize(); top = 1 + MalloryHandler::titleSize(); // activate updated layout widget()->layout()->activate(); } void MalloryClient::reset(unsigned long) // unsigned long changed { // TODO: Implementation } void MalloryClient::resize(const TQSize& s) { widget()->resize(s); } //////////////// Plugin Stuff extern "C" { TDE_EXPORT KDecorationFactory *create_factory() { return new MalloryHandler(); } } #include "malloryclient.moc"