[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-devel
Subject:    Docking - Design questions
From:       Christian Esken <c.esken () cityweb ! de>
Date:       1999-05-15 21:50:27
[Download RAW message or body]

Hi,

while working on the new K Docking Widget (KDW), I stumbled across
design questions.
There are two possible solutions and I'd like to hear your opinions
about them. In parts this is getting quite technical, so be warned.

I'm attaching the KDW sources, so you can take a look. I do presume not
everybody has the HEAD branch yet (Attention: Current working snapshot
from my HD, might NOT compile!!!).




Here we go:

Besides KDW-only questions, this is also a discussion on how the
KTMW<->KApp<->KDW classes should work together in the future. While I
think about this, the text is evolving and getting longer and longer,
so be warned again. ;-)


Todays standard docking class implementations fulfills two very
different tasks (docking/Docking class <---> show-hide/KTMW):

1. Docking widget:
   a) create the widget
   b) create a popup menu (dependent on state of main window)
   c) dock it/ undock it

2. KTMW:
   a) Show it/Hide it


I now have two options.

First option:
  Leave everything as it is.
  I feel this is wrong! The docking (widget) class should NOT deal with
  handling of other windows. The code for "hiding" is even duplicated.
  If you take a close look, you will find semantically identical code
  in the according KTMW descendant (in my test case the KMix class).

Second option:
  Remove the "show/hide main window" stuff from the docking class.
  I would emit a signal instead. This should be captured by KTMW.
  No, wrong: Better yet, KApplication should deal with this. This would
  guarantee, all docking stuff would work also when no window is open.
  (e.g. a quit_clicked() SIGNAL from DockingWidget could be handled).



I like the second is much better. I guess it will be easier to extend:
DockingWidget just emits a "dock()". KApplication (or KTMW) could then look
up ther users' docking preferences (e.g. think of a configuration option
"dock all application windows" or "dock only current main window").

But this needs coordination with KApplication, as KTMW must still know
whether the "application" is in "iconified" state or not - or if this
question doesn't make any sense, because the application currently has no
window open (this is *not* theoretic talk, just think of konqueror).

So it boils down for me that it would be the right thing if the docking
class and KApplication would cooperate (Remember: There's perhaps no
KTMW instance around). What I need:
1) KApplication needs a method to retrieve the applications state:
   Either shown or hidden. It has to be discussed what "hidden" actually
   means: "main window hidden" or "all windows hidden" or ...
2) KApplication must have slots for standard docking SIGNALs:
   quit_clicked() and lets_call_it_toggle_window_state_clicked()



Another question is whether to "Dock on iconify" or "Dock on close".
KTMW has to be touched for both: We need closeEvent() or hideEvent()
or both if we want this to be configurable.

BTW: There's still no chance to "steal" the click at the iconify button
from kwm. Is this correct, Matthias?



  Christian

-- 
Is Unix ready for the desktop? See http://www.kde.org

The                              Christian Esken
|/  Desktop                      KDE Developer
|\  Environment                  esken@kde.org

KDE - The net transparent free Unix Desktop for everyone

["docking.cpp" (text/english)]

/*
 *                     The KDE docking class
 *
 *
 *              Copyright (C) 1999 Christian Esken
 *                        esken@kde.org
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this program; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <kwm.h>
#include <kapp.h>
#include <klocale.h>

#include "docking.h"
#include <qmessagebox.h>


// --- Constructor ---
KDockWidget::KDockWidget(const QString& name, const QString& dockPixmapName)
  : QWidget(0, name, 0)
{
  baseInit();
  setPixmap(dockPixmapName);
}

// --- Constructor ---
KDockWidget::KDockWidget(const QString& name, QPixmap &dockPixmap)
  : QWidget(0, name, 0)
{
  baseInit();
  setPixmap(dockPixmap);
}


// --- set a new dock Pixmap by filename ---
void KDockWidget::setPixmap(QString& dockPixmapName)
{
  if ( dockIconName == 0 ) {
    dockPixmap = 0;
  }
  else {
    dockPixmap = new QPixmap();
    // load dock icon pixmap
    if ( dockIconName != 0 && !dockPixmap->load(dockIconName) ) {
      QString tmp;
      // !!! this should use KDE error handling functions
      tmp = i18n("Could not load ") + dockIconName;
      QMessageBox::warning(this, i18n("Error"), tmp);
    }
  }
}


// --- set a new dock Pixmap by giving a QPixmap ---
void KDockWidget::setPixmap(QPixmap& dockPixmap)
{
  this->dockPixmap = dockPixmap;
}


KDockWidget::baseInit() {
  // initialize some basic variables
  docked = false;
  pos_x = pos_y = 0;

  // Create standard popup menu for right mouse button
  popup_m = new QPopupMenu();

  // Insert standard item "Restore" into context menu of docking area
  toggleID = popup_m->insertItem(i18n("Restore"),
				 this, SLOT(toggle_window_state()));
  
  // Insert standard item "Quit" into context menu of docking area
  popup_m->insertItem(i18n("Quit"),
		      this, SLOT(emit_quit()));
}


// --- Destructor ---
KDockWidget::~KDockWidget()
{
  delete popup_m;
}


// --- Dock on Panel ---
void KDockWidget::dock()
{
  if (!docked) {
    // Tell the Panel, this widget wants a place on the docking area
    KWM::setDockWindow (this->winId());

    // that's all the space there is !!! SHOULD BE REWORKED (ask kpanel maintainer) !!!
    this->setFixedSize(24, 24);

    // finally show the docking widget on the docking area
    show();
    docked = true;
  }
}


// --- Undock from Panel ---
void KDockWidget::undock()
{
  if (docked) {
    // The widget's window has to be destroyed in order to undock from the
    // panel. Simply using hide() is not enough.
    this->destroy(true, true);

    // recreate docking widget for further dockings
    this->create(0, true, false);
    docked = false;
  }
}


// --- check whether application is in "docked" state ---
bool KDockWidget::isDocked() const
{
  return docked;
}


void KDockWidget::setMainWindow(KTMainWindow *ktmw)
{
  this->ktmw = ktmw;
}



void KDockWidget::paintEvent (QPaintEvent* )
{
  paintIcon();
}

void KDockWidget::paintIcon ()
{
  bitBlt(this, 0, 0, dockPixmap);
}

void KDockWidget::timeclick()
{
  if( this->isVisible() )
    paintIcon();
}


void KDockWidget::mousePressEvent(QMouseEvent *e)
{
  // open/close connect-window on left mouse button 
  if ( e->button() == LeftButton ) {
    toggle_window_state();
  }

  // open popup menu on right mouse button
  if ( e->button() == RightButton  || e->button() == MidButton) {
    int x = e->x() + this->x();
    int y = e->y() + this->y();

    QString text;
    if(ktmw != 0 && ktmw->isVisible())
      text = i18n("&Minimize");
    else
      text = i18n("&Restore");
    
    popup_m->changeItem(text, toggleID);
    popup_m->popup(QPoint(x, y));
    popup_m->exec();
  }

}

void KDockWidget::toggle_window_state()
{
  if(ktmw != 0) {
    if (ktmw->isVisible()) {
      // --- Toplevel was visible => hide it
      dockinginprogress = true;
      toggled = true;
      ktmw->hide();
      ktmw->recreate(0, 0, QPoint(ktmw->x(), ktmw->y()), FALSE);
      kapp->setTopWidget( ktmw );
    }
    else {
      // --- Toplevel was invisible => show it again
      toggled = false;
      ktmw->show();
      dockinginprogress = false;
      // Do not only show the window, but make it active, too
      KWM::activate(ktmw->winId());
    }
  }
}

bool KDockWidget::isToggled() const
{
  return(toggled);
}

void KDockWidget::emit_quit()
{
  emit quit_clicked();
}

#include "docking.moc"


["docking.h" (text/english)]

/*
 * KDockWidget
 *
 *              Copyright (C) 1999 Christian Esken
 *                       esken@kde.org
 * 
 * This class is based on a contribution by Harri Porten <porten@tu-harburg.de>
 * It has been reworked by Christian Esken to be a generic base class for
 * docking.
 *
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this program; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */


#ifndef _DOCKING_H_
#define _DOCKING_H_

#include <ktmainwindow.h>
#include <qpixmap.h>
#include <qpoint.h>

/**
 This class creates a widget that allows applications to display a widget
 on the docking area of the panel. The following services are provided:
 A popup menu with some standard entries is created. You can
 place further entries in there. The menu is being shown by a right-button
 click on the widget.
 Hide and show a main window  
 */
class KDockWidget : public QWidget {

  Q_OBJECT

public:
  /// Creates a docking widget and allows passing of the name of
  /// the docking icon. After the construcor has run
  KDockWidget(const QString& name=0, const QString& dockIconName=0);
  /// Overloader constructor. Only differs from the previous constructor
  /// in that you can pass the icon as a QPixmap
  KDockWidget(const QString& name=0, QPixmap &dockPixmap=0)
  /// Deletes the docking widget. Please note that the widget undocks from
  /// the panel automatically.
  ~KDockWidget();
  void setMainWindow(KTMainWindow *ktmw);
  QPixmap* dockPixmap() const;
  /// Checks, if application is in "docked" state. Returns true, if yes.
  bool isDocked() const;
  bool isToggled() const;  // !!! Remove?
  void savePosition();

public slots:
  /// Dock this widget - this means to show this widget on the docking area
  virtual void dock();
  /// Undock this widget - this means to remove this widget from the docking area
  virtual void undock();

protected:
  void paintEvent(QPaintEvent *e);
  void paintIcon();
  void baseInit();

private slots:
  void timeclick();
  void toggle_window_state();
  void mousePressEvent(QMouseEvent *e);


signals:
  void quit_clicked();

protected slots:
  void emit_quit();

protected:
  bool		docked;
  int		toggleID;
  int		pos_x;
  int		pos_y;
  KTMainWindow	*ktmw;
  QPopupMenu	*popup_m;
  QPixmap	*dockPixmap;
  bool		dockingInProgress;
  bool		toggled;  // !!! Remove ???
};

#endif



[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic