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.
tdeutils/kregexpeditor/multicontainerwidget.cpp

266 lines
7.1 KiB

/*
* Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org>
*
* 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 "multicontainerwidget.h"
#include "dragaccepter.h"
MultiContainerWidget::MultiContainerWidget( RegExpEditorWindow* editorWindow,
TQWidget* parent, const char* name)
:RegExpWidget( editorWindow, parent, name )
{
}
void MultiContainerWidget::append( RegExpWidget* child )
{
child->reparent( this, TQPoint(0,0), false );
_children.append( child );
_children.append( new DragAccepter( _editorWindow, this ) );
}
bool MultiContainerWidget::hasSelection() const
{
if ( _isSelected )
return true;
TQPtrListIterator<RegExpWidget> it(_children);
++it; // Move past the first dragAccepter
for ( ; *it; it += 2 ) {
if ( (*it)->hasSelection() ) {
return true;
}
}
return false;
}
void MultiContainerWidget::clearSelection()
{
_isSelected = false;
for ( unsigned int i = 0; i< _children.count(); i++ ) {
_children.at(i)->clearSelection();
}
}
void MultiContainerWidget::deleteSelection()
{
// run from the back to the front (which we do since we delete items on the run)
// When deleting children, delete the drag accepter to its right.
for ( int i = (int) _children.count()-2; i > 0; i -=2 ) {
RegExpWidget* child = _children.at( i );
if ( child->isSelected() ) {
delete _children.at( i+1 );
_children.remove( i+1 );
delete child;
_children.remove(i);
}
else if ( child->hasSelection() ) {
child->deleteSelection();
}
}
_isSelected = false;
update();
}
void MultiContainerWidget::addNewChild(DragAccepter *accepter, RegExpWidget *child)
{
for ( unsigned int i=0; i<_children.count(); i+= 2 ) {
RegExpWidget *ch = _children.at( i );
if ( ch == accepter ) {
// Insert the new child
_children.insert( i+1, child );
// Insert an accepter as the next element.
DragAccepter *accepter = new DragAccepter( _editorWindow, this );
_children.insert( i+2, accepter );
// These two show's must come here otherwise a paintevent
// will be invoked, where the invariant, that a accepter is located at
// every second element.
child->show();
accepter->show();
update();
return;
}
}
qFatal("Accepter not found in list");
}
bool MultiContainerWidget::updateSelection(bool parentSelected)
{
bool changed = false;
bool isSel = _isSelected;
TQMemArray<bool> oldState(_children.count());
TQMemArray<bool> newState(_children.count());
for (int i = 0; i< (int)_children.count();i++) {
oldState[i] = _children.at(i)->isSelected();
}
RegExpWidget::updateSelection( parentSelected );
int first;
int last;
// scan for the first selected item.
for (first = 1; first < (int) _children.count(); first+= 2 ) {
RegExpWidget* child = _children.at(first);
changed = child->updateSelection( _isSelected ) || changed;
newState[first] = child->isSelected();
if ( child->isSelected() )
break;
}
// scan for the last selected item
for (last = _children.count()-2; last>first; last -= 2) {
RegExpWidget* child = _children.at(last);
changed = child->updateSelection( _isSelected ) || changed;
newState[last] = child->isSelected();
if ( child->isSelected() )
break;
}
// everything between first and last must be selected.
for (int j = first+2; j<last; j+=2) {
RegExpWidget* child = _children.at(j);
changed = child->updateSelection( true ) || changed;
newState[j] = true;
}
// update drag accepters.
for (int k = 0; k< (int) _children.count(); k+=2) {
RegExpWidget* child = _children.at(k);
bool select;
if ( k == 0 || k == (int)_children.count()-1) {
// The elements at the border is only selected if the parent is selected.
select = _isSelected;
}
else {
// Drag accepters in the middle is selected if the elements at both
// sides are selected.
select = newState[k-1] && newState[k+1];
}
bool isChildSel = child->isSelected();
DragAccepter *accepter = dynamic_cast<DragAccepter*>(child);
if (accepter)
accepter->_isSelected = select;
if ( select != isChildSel )
child->repaint();
}
changed = changed || isSel != _isSelected;
if ( changed ) {
repaint();
}
return changed;
}
TQRect MultiContainerWidget::selectionRect() const
{
if ( _isSelected )
return TQRect( mapToGlobal( TQPoint(0,0) ), size() );
else {
TQRect res;
TQPtrListIterator<RegExpWidget> it(_children);
++it; // Move past the first dragAccepter
for ( ; *it; it +=2 ) {
if ( (*it)->hasSelection() ) {
TQRect childSel = (*it)->selectionRect();
if ( res.isNull() )
res = childSel;
else {
TQRect newRes;
newRes.setLeft( QMIN( res.left(), childSel.left() ) );
newRes.setTop( QMIN( res.top(), childSel.top() ) );
newRes.setRight( QMAX( res.right(), childSel.right() ) );
newRes.setBottom( QMAX( res.bottom(), childSel.bottom() ) );
res = newRes;
}
}
}
return res;
}
}
RegExpWidget* MultiContainerWidget::widgetUnderPoint( TQPoint globalPos, bool justVisibleWidgets )
{
unsigned int start, incr;
if ( justVisibleWidgets ) {
start = 1;
incr = 2;
}
else {
start = 0;
incr = 1;
}
for ( unsigned int i = start; i < _children.count(); i+=incr ) {
RegExpWidget* wid = _children.at(i)->widgetUnderPoint( globalPos, justVisibleWidgets );
if ( wid )
return wid;
}
if ( justVisibleWidgets )
return 0;
else {
return RegExpWidget::widgetUnderPoint( globalPos, justVisibleWidgets );
}
}
RegExpWidget* MultiContainerWidget::findWidgetToEdit( TQPoint globalPos )
{
for ( unsigned int i = 1; i < _children.count(); i+=2 ) {
RegExpWidget* wid = _children.at(i)->findWidgetToEdit( globalPos );
if ( wid )
return wid;
}
return 0;
}
void MultiContainerWidget::selectWidget( bool sel )
{
RegExpWidget::selectWidget( sel );
TQPtrListIterator<RegExpWidget> it(_children);
for ( ; *it ; ++it ) {
(*it)->selectWidget( sel );
}
update();
}
void MultiContainerWidget::updateAll()
{
for ( TQPtrListIterator<RegExpWidget> it(_children); *it ; ++it ) {
(*it)->updateAll();
}
RegExpWidget::updateAll();
}
void MultiContainerWidget::updateCursorRecursively()
{
for ( TQPtrListIterator<RegExpWidget> it(_children); *it ; ++it ) {
(*it)->updateCursorRecursively();
}
updateCursorShape();
}