00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
#include <qframe.h>
00021
#include <qpainter.h>
00022
#include <qtimer.h>
00023
#include <qstyle.h>
00024
#include <kdebug.h>
00025
00026
#include "splitter.h"
00027
00028
00029 Splitter::Splitter(
QWidget *parent,
const char *name)
00030 :
QWidget(parent, name)
00031 {
00032
_or = Horizontal;
00033
00034
handlelist.setAutoDelete(
true);
00035 }
00036
00037
00038 Splitter::~Splitter()
00039 {}
00040
00041
00042 void Splitter::setOrientation(Orientation orient)
00043 {
00044
if (orient !=
_or) {
00045
if (!
childlist.isEmpty()) {
00046
if (
hasMultipleChildren()) {
00047
kdDebug(9000) <<
"Cannot change the orientation of a splitter with several widgets." <<
endl;
00048
return;
00049 }
00050
if (orient == Horizontal) {
00051
SplitterHandle *handle =
new SplitterHandle(
childlist.first(),
this,
"handle");
00052
00053
handlelist.append(handle);
00054 }
else {
00055
handlelist.remove((uint)0);
00056 }
00057 }
00058
00059
_or = orient;
00060
doLayout();
00061 }
00062 }
00063
00064
00065 Qt::Orientation
Splitter::orientation()
const
00066
{
00067
return _or;
00068 }
00069
00070
00071 bool Splitter::hasMultipleChildren()
const
00072
{
00073
return childlist.count() > 1;
00074 }
00075
00076
00077 QWidget *
Splitter::firstChild()
00078 {
00079
return childlist.first();
00080 }
00081
00082
00083 int Splitter::handleWidth()
const
00084
{
00085
return (
orientation() == Horizontal)? style().pixelMetric(QStyle::PM_SplitterWidth,
this) : 0;
00086 }
00087
00088
00089 void Splitter::addChild(
QWidget *w)
00090 {
00091
kdDebug(9000) <<
"add child" <<
endl;
00092
00093
if (
childlist.count()) {
00094
00095
00096
splitChild(
childlist.last(), w);
00097 }
else {
00098
childlist.append(w);
00099
if (
orientation() == Horizontal) {
00100
SplitterHandle *handle =
new SplitterHandle(w,
this,
"handle");
00101
handlelist.append(handle);
00102 }
00103 }
00104
00105
doLayout();
00106 }
00107
00108
00109 void Splitter::splitChild(
QWidget *old,
QWidget *w)
00110 {
00111
#if 0
00112
kdDebug(9000) <<
"splitChild - Old list of splitter children:" <<
endl;
00113
QPtrListIterator<QWidget> it1(
childlist);
00114
for (; it1.current(); ++it1)
00115
kdDebug(9000) << it1.current()->name() <<
endl;
00116
#endif
00117
00118
int offset = 0;
00119
for (uint i = 0; i <
childlist.count(); ++i) {
00120
if (
childlist.at(i) == old) {
00121
childlist.insert(i+1, w);
00122
if (
orientation() == Horizontal) {
00123
SplitterHandle *handle =
new SplitterHandle(w,
this,
"handle");
00124
handlelist.insert(i+1, handle);
00125 }
00126
if (i+1 !=
childlist.count()-1) {
00127
sizes.insert(
sizes.at(i),
sizes[i]/2 -
handleWidth());
00128
sizes[i+1] =
sizes[i]/2;
00129 }
else {
00130
int total = (
orientation() == Horizontal)? width() : height();
00131
sizes.insert(
sizes.at(i), (total-offset)/2);
00132 }
00133
doLayout();
00134
return;
00135 }
00136 offset +=
sizes[i];
00137 offset +=
handleWidth();
00138 }
00139
00140
kdDebug(9000) <<
"Huh? Old child not in splitter" <<
endl;
00141 }
00142
00143
00144 void Splitter::replaceChild(
QWidget *old,
QWidget *w)
00145 {
00146
for (uint i=0; i <
childlist.count(); ++i)
00147
if (
childlist.at(i) == old) {
00148
childlist.remove(i);
00149
if (
orientation() == Horizontal)
00150
handlelist.remove(i);
00151
childlist.insert(i, w);
00152
if (
orientation() == Horizontal) {
00153
SplitterHandle *handle =
new SplitterHandle(w,
this,
"handle");
00154
handlelist.insert(i, handle);
00155 }
00156
doLayout();
00157
return;
00158 }
00159
00160
kdDebug(9000) <<
"Huh? Old child not in splitter" <<
endl;
00161 }
00162
00163
00164 void Splitter::moveSplitter(
QWidget *w,
int pos)
00165 {
00166
int offset = 0;
00167
for (uint i=0; i <
childlist.count(); ++i) {
00168
if (
childlist.at(i) == w) {
00169
if (i !=
childlist.count()) {
00170
sizes[i] = pos-offset;
00171
break;
00172 }
00173 }
00174 offset +=
sizes[i];
00175 offset +=
handleWidth();
00176 }
00177
00178
doLayout();
00179 }
00180
00181
00182 void Splitter::doLayout()
00183 {
00184 setUpdatesEnabled(
false);
00185
00186
if (
orientation() == Horizontal) {
00187
00188
int offset = 0;
00189 uint i;
00190
for (i=0; i+1 <
childlist.count(); ++i) {
00191
sizes[i] = QMAX(
sizes[i],
childlist.at(i)->minimumSizeHint().width());
00192
childlist.at(i)->setGeometry(offset, 0,
sizes[i], height());
00193 offset +=
childlist.at(i)->width();
00194
handlelist.at(i)->setGeometry(offset, 0, style().pixelMetric(QStyle::PM_SplitterWidth,
this), height());
00195
handlelist.at(i)->show();
00196 offset +=
handlelist.at(i)->width();
00197 }
00198
00199
if (
childlist.count()) {
00200
childlist.at(i)->setGeometry(offset, 0, width()-offset, height());
00201
handlelist.at(i)->hide();
00202 }
00203
00204 }
else {
00205
00206
int offset = 0;
00207 uint i;
00208
for (i=0; i+1 <
childlist.count(); ++i) {
00209
sizes[i] = QMAX(
sizes[i],
childlist.at(i)->minimumSizeHint().height());
00210
childlist.at(i)->setGeometry(0, offset, width(),
sizes[i]);
00211 offset +=
childlist.at(i)->height();
00212 }
00213
00214
if (
childlist.count())
00215
childlist.at(i)->setGeometry(0, offset, width(), height()-offset);
00216
00217 }
00218
00219 setUpdatesEnabled(
true);
00220 }
00221
00222
00223
00224 QSize Splitter::minimumSizeHint()
const
00225
{
00226
int extent = 0;
00227
for (uint i = 0; i <
childlist.count(); ++i) {
00228
00229
Splitter *that = (
Splitter*)
this;
00230
QSize s = that->
childlist.at(i)->minimumSizeHint();
00231 extent = QMAX(extent, (
orientation()==Horizontal)? s.height() : s.width());
00232 }
00233
return (
orientation()==Horizontal)?
QSize(0, extent) :
QSize(extent, 0);
00234 }
00235
00236
00237 void Splitter::childEvent(
QChildEvent *e)
00238 {
00239
if (e->type() != QEvent::ChildRemoved)
00240
return;
00241
00242
QObject *o = e->child();
00243
00244
for (uint i=0; i<
childlist.count(); ++i) {
00245
if (
childlist.at(i) == o) {
00246
childlist.remove(i);
00247
if (
orientation() == Horizontal)
00248
handlelist.remove(i);
00249
if (i ==
childlist.count())
00250
sizes.remove(i-1);
00251
else
00252
sizes.remove(i);
00253
doLayout();
00254
if (
childlist.count() < 2)
00255 QTimer::singleShot(0,
this, SLOT(
collapse()));
00256
break;
00257 }
00258 }
00259 }
00260
00261
00262 void Splitter::collapse()
00263 {
00264 emit
collapsed(
this);
00265 }
00266
00267
00268 void Splitter::resizeEvent(
QResizeEvent *)
00269 {
00270
doLayout();
00271 }
00272
00273
00274 SplitterBar::SplitterBar(
QWidget *parent,
const char *name)
00275 :
QFrame(parent, name)
00276 {
00277 setFrameStyle(Panel | Raised);
00278 setLineWidth(1);
00279 setFixedHeight(fontMetrics().lineSpacing()+2);
00280
00281
offset = 0;
00282 }
00283
00284
00285 SplitterBar::~SplitterBar()
00286 {}
00287
00288
00289 void SplitterBar::mouseMoveEvent(
QMouseEvent *e)
00290 {
00291
if (e->state() & LeftButton) {
00292
QWidget *p = parentWidget();
00293
QWidget *gp = p->parentWidget();
00294
if (!gp->inherits(
"Splitter"))
00295
return;
00296
00297
00298
00299
if (static_cast<Splitter*>(gp)->orientation() == Horizontal) {
00300 p = gp;
00301 gp = p->parentWidget();
00302
if (!gp->inherits(
"Splitter"))
00303
return;
00304 }
00305
int pos = gp->mapFromGlobal(e->globalPos()).y() +
offset;
00306 static_cast<Splitter*>(gp)->moveSplitter(p, pos);
00307 }
00308 }
00309
00310
00311 void SplitterBar::mousePressEvent(
QMouseEvent *e)
00312 {
00313
if ( e->button() & LeftButton )
00314
offset = height()-e->pos().y();
00315 }
00316
00317
00318 void SplitterBar::childEvent(
QChildEvent *e)
00319 {
00320
if (e->type() == QEvent::ChildInserted && e->child()->isWidgetType())
00321 e->child()->installEventFilter(
this);
00322
else if (e->type() == QEvent::ChildRemoved && e->child()->isWidgetType())
00323 e->child()->removeEventFilter(
this);
00324 }
00325
00326
00327 bool SplitterBar::eventFilter(
QObject *o,
QEvent *e)
00328 {
00329
if (e->type() == QEvent::MouseButtonPress)
00330
mousePressEvent(static_cast<QMouseEvent*>(e));
00331
else if(e->type() == QEvent::MouseMove)
00332
mouseMoveEvent(static_cast<QMouseEvent*>(e));
00333
00334
return QWidget::eventFilter(o, e);
00335 }
00336
00337
00338 SplitterHandle::SplitterHandle(
QWidget *embeddedSibling,
Splitter *parent,
const char *name)
00339 :
QWidget(parent, name)
00340 {
00341
sibling = embeddedSibling;
00342 setCursor(splitHCursor);
00343
00344 }
00345
00346
00347 SplitterHandle::~SplitterHandle()
00348 {}
00349
00350
00351 void SplitterHandle::mouseMoveEvent(
QMouseEvent *e)
00352 {
00353
if (e->state() & LeftButton) {
00354
int pos = parentWidget()->mapFromGlobal(e->globalPos()).x() +
offset;
00355 static_cast<Splitter*>(parentWidget())->moveSplitter(
sibling, pos);
00356 }
00357 }
00358
00359
00360 void SplitterHandle::mousePressEvent(
QMouseEvent *e)
00361 {
00362
if ( e->button() & LeftButton )
00363
offset = -e->pos().x();
00364 }
00365
00366
00367 void SplitterHandle::paintEvent(
QPaintEvent *)
00368 {
00369
QPainter p(
this);
00370 style().drawPrimitive(QStyle::PE_Splitter, &p,
QRect(0, 0, width(), height()), colorGroup(), QStyle::Style_Horizontal);
00371 }
00372
00373
#include "splitter.moc"