25#include "kspread_canvas.h"
26#include "kspread_cell.h"
27#include "kspread_doc.h"
28#include "kspread_editors.h"
29#include "kspread_sheet.h"
30#include "kspread_view.h"
31#include "kspread_util.h"
44class Selection::Private
51 anchor = TQPoint(1,1);
52 cursor = TQPoint(1,1);
53 marker = TQPoint(1,1);
55 colors.push_back(TQt::red);
56 colors.push_back(TQt::blue);
57 colors.push_back(TQt::magenta);
58 colors.push_back(TQt::darkRed);
59 colors.push_back(TQt::darkGreen);
60 colors.push_back(TQt::darkMagenta);
61 colors.push_back(TQt::darkCyan);
62 colors.push_back(TQt::darkYellow);
64 multipleSelection =
false;
66 activeElement = Iterator();
67 activeSubRegionStart = 0;
68 activeSubRegionLength = 0;
76 TQValueList<TQColor> colors;
78 bool multipleSelection : 1;
80 Selection::Iterator activeElement;
81 uint activeSubRegionStart;
82 uint activeSubRegionLength;
90Selection::Selection(
View *view)
91 : TQObject(view),
Region(1,1)
93 d =
new Private(view);
94 d->activeSubRegionStart = 0;
95 d->activeSubRegionLength = 1;
98Selection::Selection(
const Selection& selection)
99 : TQObject(selection.d->view),
Region()
102 d =
new Private(selection.d->view);
103 d->sheet = selection.d->sheet;
104 d->activeSubRegionStart = 0;
105 d->activeSubRegionLength = cells().count();
108Selection::~Selection()
113void Selection::initialize(
const TQPoint& point, Sheet* sheet)
115 if (!util_isPointValid(point))
118 if (!d->view->activeSheet())
129 sheet = d->view->activeSheet();
133 Region changedRegion(*
this);
134 changedRegion.add(extendToMergedAreas(TQRect(d->anchor,d->marker)));
136 TQPoint topLeft(point);
137 Cell* cell = d->view->activeSheet()->cellAt(point);
141 topLeft = TQPoint(cell->
column(), cell->
row());
148 fixSubRegionDimension();
149 Iterator it =
cells().begin() += d->activeSubRegionStart + d->activeSubRegionLength;
150 if (it !=
insert(it, topLeft, sheet))
155 Element* element = *(
cells().begin() += d->activeSubRegionStart);
157 d->activeSubRegionLength = 1;
158 if (element && element->type() == Element::Point)
160 Point* point =
static_cast<Point*
>(element);
161 point->setColor(d->colors[
cells().size() % d->colors.size()]);
163 else if (element && element->type() == Element::Range)
165 Range* range =
static_cast<Range*
>(element);
166 range->setColor(d->colors[
cells().size() % d->colors.size()]);
169 d->activeElement =
cells().begin();
171 if (changedRegion == *
this)
173 emit changed(
Region(topLeft, sheet));
176 changedRegion.add(topLeft, sheet);
178 emit changed(changedRegion);
181void Selection::initialize(
const TQRect& range, Sheet* sheet)
183 if (!util_isRectValid(range) || ( range == TQRect(0,0,1,1) ))
194 sheet = d->view->activeSheet();
198 Region changedRegion(*
this);
199 changedRegion.add(extendToMergedAreas(TQRect(d->anchor,d->marker)));
201 TQPoint topLeft(range.topLeft());
202 Cell* cell = d->view->activeSheet()->cellAt(topLeft);
206 topLeft = TQPoint(cell->
column(), cell->
row());
209 TQPoint bottomRight(range.bottomRight());
210 cell = d->view->activeSheet()->cellAt(bottomRight);
214 bottomRight = TQPoint(cell->
column(), cell->
row());
218 d->cursor = bottomRight;
219 d->marker = bottomRight;
221 fixSubRegionDimension();
222 Iterator it =
cells().begin() += d->activeSubRegionStart + d->activeSubRegionLength;
223 if (it !=
insert(it, TQRect(topLeft, bottomRight), sheet))
229 Element* element = *(
cells().begin() += d->activeSubRegionStart);
231 d->activeSubRegionLength = 1;
232 if (element && element->type() == Element::Point)
234 Point* point =
static_cast<Point*
>(element);
235 point->setColor(d->colors[
cells().size() % d->colors.size()]);
237 else if (element && element->type() == Element::Range)
239 Range* range =
static_cast<Range*
>(element);
240 range->setColor(d->colors[
cells().size() % d->colors.size()]);
243 d->activeElement =
cells().begin();
245 if (changedRegion == *
this)
249 changedRegion.add(TQRect(topLeft, bottomRight), sheet);
251 emit changed(changedRegion);
254void Selection::initialize(
const Region& region, Sheet* sheet)
267 sheet = d->view->activeSheet();
271 Region changedRegion(*
this);
272 changedRegion.add(extendToMergedAreas(TQRect(d->anchor,d->marker)));
278 if (element && element->type() == Element::Point)
280 Point* point =
static_cast<Point*
>(element);
281 point->setColor(d->colors[
cells().size() % d->colors.size()]);
283 else if (element && element->type() == Element::Range)
285 Range* range =
static_cast<Range*
>(element);
286 range->setColor(d->colors[
cells().size() % d->colors.size()]);
289 TQPoint topLeft(
cells().last()->rect().normalize().topLeft());
290 Cell* cell = d->view->activeSheet()->cellAt(topLeft);
294 topLeft = TQPoint(cell->
column(), cell->
row());
297 TQPoint bottomRight(
cells().last()->rect().normalize().bottomRight());
298 cell = d->view->activeSheet()->cellAt(bottomRight);
302 bottomRight = TQPoint(cell->
column(), cell->
row());
307 d->marker = bottomRight;
309 d->activeElement = --
cells().end();
310 d->activeSubRegionStart = 0;
311 d->activeSubRegionLength =
cells().count();
313 if (changedRegion == *
this)
317 changedRegion.add( region );
319 emit changed(changedRegion);
322void Selection::update()
327void Selection::update(
const TQPoint& point)
329 uint count =
cells().count();
334 d->activeSubRegionLength +=
cells().count() - count;
337 if (d->activeElement ==
cells().end())
343 Sheet* sheet = (*d->activeElement)->sheet();
344 if (sheet != d->view->activeSheet())
347 d->activeSubRegionLength +=
cells().count() - count;
351 TQPoint topLeft(point);
352 Cell* cell = d->view->activeSheet()->cellAt(point);
356 topLeft = TQPoint(cell->
column(), cell->
row());
359 if (topLeft == d->marker)
364 TQRect area1 = (*d->activeElement)->rect().normalize();
365 TQRect newRange = extendToMergedAreas(TQRect(d->anchor, topLeft));
367 Element* oldElement = *d->activeElement;
369 Iterator it =
cells().remove(d->activeElement);
372 d->activeElement =
insert(it, newRange, sheet, d->multipleSelection);
373 d->activeSubRegionLength +=
cells().count() - count;
379 if (d->activeElement ==
cells().end())
384 TQRect area2 = (*d->activeElement)->rect().normalize();
387 bool newLeft = area1.left() != area2.left();
388 bool newTop = area1.top() != area2.top();
389 bool newRight = area1.right() != area2.right();
390 bool newBottom = area1.bottom() != area2.bottom();
393 int farLeft = TQMIN(area1.left(), area2.left());
394 int innerLeft = TQMAX(area1.left(), area2.left());
396 int farTop = TQMIN(area1.top(), area2.top());
397 int innerTop = TQMAX(area1.top(), area2.top());
399 int farRight = TQMAX(area1.right(), area2.right());
400 int innerRight = TQMIN(area1.right(), area2.right());
402 int farBottom = TQMAX(area1.bottom(), area2.bottom());
403 int innerBottom = TQMIN(area1.bottom(), area2.bottom());
407 changedRegion.
add(TQRect(TQPoint(farLeft, innerTop),
408 TQPoint(innerLeft-1, innerBottom)));
411 changedRegion.
add(TQRect(TQPoint(farLeft, farTop),
412 TQPoint(innerLeft-1, innerTop-1)));
416 changedRegion.
add(TQRect(TQPoint(farLeft, innerBottom+1),
417 TQPoint(innerLeft-1, farBottom)));
423 changedRegion.
add(TQRect(TQPoint(innerLeft, farTop),
424 TQPoint(innerRight, innerTop-1)));
429 changedRegion.
add(TQRect(TQPoint(innerRight+1, innerTop),
430 TQPoint(farRight, innerBottom)));
433 changedRegion.
add(TQRect(TQPoint(innerRight+1, farTop),
434 TQPoint(farRight, innerTop-1)));
438 changedRegion.
add(TQRect(TQPoint(innerRight+1, innerBottom+1),
439 TQPoint(farRight, farBottom)));
445 changedRegion.
add(TQRect(TQPoint(innerLeft, innerBottom+1),
446 TQPoint(innerRight, farBottom)));
452 emit changed(changedRegion);
455void Selection::extend(
const TQPoint& point, Sheet* sheet)
457 if (!util_isPointValid(point))
462 initialize(point, sheet);
465 if (d->activeElement ==
cells().end())
479 sheet = d->view->activeSheet();
483 Region changedRegion =
Region(extendToMergedAreas(TQRect(d->marker,d->marker)));
485 TQPoint topLeft(point);
486 Cell* cell = d->view->activeSheet()->cellAt(point);
490 topLeft = TQPoint(cell->
column(), cell->
row());
493 uint count =
cells().count();
494 if (d->multipleSelection)
496 d->activeElement =
insert(++d->activeElement, point, sheet,
false);
501 d->activeElement = --
cells().end();
503 d->anchor = (*d->activeElement)->rect().topLeft();
504 d->cursor = (*d->activeElement)->rect().bottomRight();
505 d->marker = d->cursor;
507 d->activeSubRegionLength +=
cells().count() - count;
509 changedRegion.
add(topLeft, sheet);
510 changedRegion.
add(*
this);
512 emit changed(changedRegion);
515void Selection::extend(
const TQRect& range, Sheet* sheet)
518 if (!util_isRectValid(range) || (range == TQRect(0,0,1,1)))
523 initialize(range, sheet);
526 if (d->activeElement ==
cells().end())
540 sheet = d->view->activeSheet();
544 TQPoint topLeft(range.topLeft());
545 Cell* cell = d->view->activeSheet()->cellAt(topLeft);
549 topLeft = TQPoint(cell->
column(), cell->
row());
552 TQPoint bottomRight(range.bottomRight());
553 cell = d->view->activeSheet()->cellAt(bottomRight);
557 bottomRight = TQPoint(cell->
column(), cell->
row());
562 d->marker = bottomRight;
564 uint count =
cells().count();
566 if (d->multipleSelection)
568 d->activeElement =
insert(++d->activeElement, extendToMergedAreas(TQRect(topLeft, bottomRight)).normalize(), sheet,
false);
569 element = (d->activeElement ==
cells().end()) ? 0 : *d->activeElement;
573 element =
add(extendToMergedAreas(TQRect(topLeft, bottomRight)).normalize(), sheet);
574 d->activeElement = --
cells().end();
576 if (element && element->type() == Element::Point)
578 Point* point =
static_cast<Point*
>(element);
579 point->setColor(d->colors[
cells().size() % d->colors.size()]);
581 else if (element && element->type() == Element::Range)
583 Range* range =
static_cast<Range*
>(element);
584 range->setColor(d->colors[
cells().size() % d->colors.size()]);
587 d->activeSubRegionLength +=
cells().count() - count;
592void Selection::extend(
const Region& region)
597 uint count =
cells().count();
598 ConstIterator end(region.constEnd());
599 for (ConstIterator it = region.constBegin(); it != end; ++it)
602 if (!element)
continue;
603 if (element->type() == Element::Point)
605 Point* point =
static_cast<Point*
>(element);
606 extend(point->pos(), element->sheet());
610 extend(element->rect(), element->sheet());
614 d->activeSubRegionLength +=
cells().count() - count;
628const TQPoint& Selection::anchor()
const
633const TQPoint& Selection::cursor()
const
638const TQPoint& Selection::marker()
const
648TQRect Selection::selectionHandleArea()
const
655 column = d->marker.x();
660 column = lastRange().right();
661 row = lastRange().bottom();
663 const Cell* cell = d->view->activeSheet()->cellAt(column, row);
665 double xpos = d->view->activeSheet()->dblColumnPos( column );
666 double ypos = d->view->activeSheet()->dblRowPos( row );
667 double width = cell->
dblWidth( column );
670 TQPoint rightBottom( d->view->doc()->zoomItX( xpos + width ),
671 d->view->doc()->zoomItY( ypos + height ) );
673 TQRect handle( ( rightBottom.x() - 2 ),
674 ( rightBottom.y() - 2 ),
680TQString Selection::name(Sheet* sheet)
const
685void Selection::setSheet(Sheet* sheet)
690Sheet* Selection::sheet()
const
695void Selection::setActiveElement(
const TQPoint& point)
698 Iterator end =
cells().end();
699 for (Iterator it =
cells().begin(); it != end; ++it)
701 TQRect range = (*it)->rect();
702 if (range.topLeft() == point || range.bottomRight() == point)
704 d->anchor = range.topLeft();
705 d->cursor = range.bottomRight();
706 d->marker = range.bottomRight();
707 d->activeElement = it;
708 d->activeSubRegionStart = counter;
709 d->activeSubRegionLength = 1;
710 if (d->view->canvasWidget()->editor())
712 d->view->canvasWidget()->editor()->setCursorToRange(counter);
719void Selection::setActiveElement(uint pos)
721 if (pos >=
cells().count())
723 kdDebug() <<
"Selection::setActiveElement: position exceeds list" << endl;
724 d->activeElement =
cells().begin();
728 Iterator it =
cells().begin() += pos;
729 TQRect range = (*it)->rect();
730 d->anchor = range.topLeft();
731 d->cursor = range.bottomRight();
732 d->marker = range.bottomRight();
733 d->activeElement = it;
738 return (d->activeElement ==
cells().end()) ? 0 : *d->activeElement;
743 d->activeSubRegionStart = 0;
744 d->activeSubRegionLength = 0;
746 d->activeElement =
cells().begin();
749void Selection::clearSubRegion()
759 Iterator it =
cells().begin();
760 Iterator end = it += d->activeSubRegionStart;
761 end += d->activeSubRegionLength;
766 it =
cells().remove(it);
768 d->activeSubRegionLength = 0;
769 d->activeElement = it;
773void Selection::fixSubRegionDimension()
775 if (d->activeSubRegionStart >
cells().count())
777 kdDebug() <<
"Selection::fixSubRegionDimension: start position exceeds list" << endl;
778 d->activeSubRegionStart = 0;
779 d->activeSubRegionLength =
cells().count();
782 if (d->activeSubRegionStart + d->activeSubRegionLength >
cells().count())
784 kdDebug() <<
"Selection::fixSubRegionDimension: length exceeds list" << endl;
785 d->activeSubRegionLength =
cells().count() - d->activeSubRegionStart;
790void Selection::setActiveSubRegion(uint start, uint length)
793 d->activeSubRegionStart = start;
794 d->activeSubRegionLength = length;
795 fixSubRegionDimension();
796 d->activeElement =
cells().begin() += d->activeSubRegionStart;
799TQString Selection::activeSubRegionName()
const
806 Iterator it =
cells().begin();
807 it += d->activeSubRegionStart;
809 end += d->activeSubRegionLength;
812 names += (*it++)->name(d->sheet);
815 return names.isEmpty() ?
"" : names.join(
";");
818void Selection::setMultipleSelection(
bool state)
820 d->multipleSelection = state;
823const TQValueList<TQColor>& Selection::colors()
const
828TQRect Selection::lastRange(
bool extend)
const
830 TQRect selection = TQRect(d->anchor, d->marker).normalize();
831 return extend ? extendToMergedAreas(selection) : selection;
834TQRect Selection::selection(
bool extend)
const
836 TQRect selection = TQRect(d->anchor, d->marker).normalize();
837 return extend ? extendToMergedAreas(selection) : selection;
840TQRect Selection::extendToMergedAreas(TQRect area)
const
842 if (!d->view->activeSheet())
845 area = area.normalize();
846 const Cell *cell = d->view->activeSheet()->cellAt(area.left(), area.top());
848 if( Region::Range(area).isColumn() || Region::Range(area).isRow() )
867 int left=area.left();
868 int bottom=area.bottom();
869 int right=area.right();
870 for (
int x = area.left(); x <= area.right(); x++ )
871 for (
int y = area.top(); y <= area.bottom(); y++ )
873 cell = d->view->activeSheet()->cellAt( x, y );
882 left=TQMIN(left,cell->
column());
883 top=TQMIN(top,cell->
row());
889 area.setCoords(left,top,right,bottom);
894Selection::Region::Point* Selection::createPoint(
const TQPoint& point)
const
896 return new Point(point);
899Selection::Region::Point* Selection::createPoint(
const TQString&
string)
const
901 return new Point(
string);
904Selection::Region::Point* Selection::createPoint(
const Point& point)
const
906 return new Point(point);
909Selection::Region::Range* Selection::createRange(
const TQRect& rect)
const
911 return new Range(rect);
914Selection::Region::Range* Selection::createRange(
const TQString&
string)
const
916 return new Range(
string);
919Selection::Region::Range* Selection::createRange(
const Range& range)
const
921 return new Range(range);
928Selection::Point::Point(
const TQPoint& point)
931 m_columnFixed(false),
936Selection::Point::Point(
const TQString&
string)
939 m_columnFixed(false),
949 if (
string[p++] ==
'$')
951 m_columnFixed =
true;
955 int result =
string.find( TQRegExp(
"[^A-Za-z]+"), p );
956 if (
string[result] ==
'$')
966Selection::Range::Range(
const TQRect& range)
976Selection::Range::Range(
const TQString&
string)
989 int delimiterPos =
string.find(
':');
990 if (delimiterPos == -1)
995 Selection::Point ul(
string.left(delimiterPos));
996 Selection::Point lr(
string.mid(delimiterPos + 1));
998 if (!ul.isValid() || !lr.isValid())
1002 m_leftFixed = ul.columnFixed();
1003 m_rightFixed = lr.columnFixed();
1004 m_topFixed = ul.rowFixed();
1005 m_bottomFixed = lr.rowFixed();
1009#include "selection.moc"
double dblHeight(int _row=-1, const Canvas *_canvas=0L) const
int row() const
Returns the cell's row.
TQValueList< Cell * > obscuringCells() const
bool doesMergeCells() const
int column() const
Returns the cell's column.
double dblWidth(int _col=-1, const Canvas *_canvas=0L) const
bool isPartOfMerged() const
If this cell is part of a merged cell, then the marker may never reside on this cell.
Represents the position of a single cell in a workbook.
Represents a region within a workbook.
Base class for region elements, which can be points or ranges.
The one for all class for points and ranges.
Element * add(const TQPoint &point, Sheet *sheet=0)
Adds the point point to this region.
virtual void clear()
Deletes all elements of the region.
TQString name(Sheet *originSheet=0) const
TQValueList< Element * > & cells() const
virtual Element * eor(const TQPoint &point, Sheet *sheet=0)
Iterator insert(Iterator iterator, const TQPoint &point, Sheet *, bool multi=true)
bool isColumnOrRowSelected() const
The View class displays a KSpread document.