diff options
Diffstat (limited to 'kspread/selection.cpp')
| -rw-r--r-- | kspread/selection.cpp | 1009 | 
1 files changed, 1009 insertions, 0 deletions
| diff --git a/kspread/selection.cpp b/kspread/selection.cpp new file mode 100644 index 000000000..f05a6db50 --- /dev/null +++ b/kspread/selection.cpp @@ -0,0 +1,1009 @@ +/* This file is part of the KDE project +   Copyright (C) 1998, 1999 Torben Weis <weis@kde.org> +   Copyright (C) 2005-2006 Stefan Nikolaus <stefan.nikolaus@kdemail.net> + +   This library 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 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 <tqregexp.h> + +#include <kdebug.h> + +#include "kspread_canvas.h" +#include "kspread_cell.h" +#include "kspread_doc.h" +#include "kspread_editors.h" +#include "kspread_sheet.h" +#include "kspread_view.h" +#include "kspread_util.h" + +#include "selection.h" + +// TODO Stefan: Substract points in selections +// TODO Stefan: KPart signal (kspread_events.h) + +using namespace KSpread; + +/*************************************************************************** +  class Selection::Private +****************************************************************************/ + +class Selection::Private +{ +public: +  Private(View *v) +  { +    view = v; +    sheet = 0; +    anchor = TQPoint(1,1); +    cursor = TQPoint(1,1); +    marker = TQPoint(1,1); + +    colors.push_back(TQt::red); +    colors.push_back(TQt::blue); +    colors.push_back(TQt::magenta); +    colors.push_back(TQt::darkRed); +    colors.push_back(TQt::darkGreen); +    colors.push_back(TQt::darkMagenta); +    colors.push_back(TQt::darkCyan); +    colors.push_back(TQt::darkYellow); + +    multipleSelection = false; + +    activeElement = Iterator(); +    activeSubRegionStart = 0; +    activeSubRegionLength = 0; +  } + +  View*  view; +  Sheet* sheet; +  TQPoint anchor; +  TQPoint cursor; +  TQPoint marker; +  TQValueList<TQColor> colors; + +  bool multipleSelection : 1; + +  Selection::Iterator activeElement; +  uint activeSubRegionStart; +  uint activeSubRegionLength; +}; + +/*************************************************************************** +  class Selection +****************************************************************************/ +namespace KSpread { + +Selection::Selection(View *view) +  : TQObject(view), Region(1,1) +{ +  d = new Private(view); +  d->activeSubRegionStart = 0; +  d->activeSubRegionLength = 1; +} + +Selection::Selection(const Selection& selection) +  : TQObject(selection.d->view), Region() +{ +/*  kdDebug() << k_funcinfo << endl;*/ +  d = new Private(selection.d->view); +  d->sheet = selection.d->sheet; +  d->activeSubRegionStart = 0; +  d->activeSubRegionLength = cells().count(); +} + +Selection::~Selection() +{ +  delete d; +} + +void Selection::initialize(const TQPoint& point, Sheet* sheet) +{ +    if (!util_isPointValid(point)) +        return; + +    if (!d->view->activeSheet()) +	    return; + +  if (!sheet) +  { +    if (d->sheet) +    { +      sheet = d->sheet; +    } +    else +    { +      sheet = d->view->activeSheet(); +    } +  } + +  Region changedRegion(*this); +  changedRegion.add(extendToMergedAreas(TQRect(d->anchor,d->marker))); + +  TQPoint topLeft(point); +  Cell* cell = d->view->activeSheet()->cellAt(point); +  if (cell->isObscured() && cell->isPartOfMerged()) +  { +    cell = cell->obscuringCells().first(); +    topLeft = TQPoint(cell->column(), cell->row()); +  } + +  d->anchor = topLeft; +  d->cursor = point; +  d->marker = topLeft; + +  fixSubRegionDimension(); // TODO remove this sanity check +  Iterator it = cells().begin() += d->activeSubRegionStart + d->activeSubRegionLength; +  if (it != insert(it, topLeft, sheet/*, true*/)) +  { +    // if the point was inserted +    clearSubRegion(); +  } +  Element* element = *(cells().begin() += d->activeSubRegionStart); +  // we end up with one element in the subregion +  d->activeSubRegionLength = 1; +  if (element && element->type() == Element::Point) +  { +    Point* point = static_cast<Point*>(element); +    point->setColor(d->colors[cells().size() % d->colors.size()]); +  } +  else if (element && element->type() == Element::Range) +  { +    Range* range = static_cast<Range*>(element); +    range->setColor(d->colors[cells().size() % d->colors.size()]); +  } + +  d->activeElement = cells().begin(); + +  if (changedRegion == *this) +  { +    emit changed(Region(topLeft, sheet)); +    return; +  } +  changedRegion.add(topLeft, sheet); + +  emit changed(changedRegion); +} + +void Selection::initialize(const TQRect& range, Sheet* sheet) +{ +    if (!util_isRectValid(range) || ( range == TQRect(0,0,1,1) )) +        return; + +  if (!sheet) +  { +    if (d->sheet) +    { +      sheet = d->sheet; +    } +    else +    { +      sheet = d->view->activeSheet(); +    } +  } + +  Region changedRegion(*this); +  changedRegion.add(extendToMergedAreas(TQRect(d->anchor,d->marker))); + +  TQPoint topLeft(range.topLeft()); +  Cell* cell = d->view->activeSheet()->cellAt(topLeft); +  if (cell->isObscured() && cell->isPartOfMerged()) +  { +    cell = cell->obscuringCells().first(); +    topLeft = TQPoint(cell->column(), cell->row()); +  } + +  TQPoint bottomRight(range.bottomRight()); +  cell = d->view->activeSheet()->cellAt(bottomRight); +  if (cell->isObscured() && cell->isPartOfMerged()) +  { +    cell = cell->obscuringCells().first(); +    bottomRight = TQPoint(cell->column(), cell->row()); +  } + +  d->anchor = topLeft; +  d->cursor = bottomRight; +  d->marker = bottomRight; + +  fixSubRegionDimension(); // TODO remove this sanity check +  Iterator it = cells().begin() += d->activeSubRegionStart + d->activeSubRegionLength; +  if (it != insert(it, TQRect(topLeft, bottomRight), sheet/*, true*/)) +  { +    // if the range was inserted +    clearSubRegion(); +  } + +  Element* element = *(cells().begin() += d->activeSubRegionStart); +  // we end up with one element in the subregion +  d->activeSubRegionLength = 1; +  if (element && element->type() == Element::Point) +  { +    Point* point = static_cast<Point*>(element); +    point->setColor(d->colors[cells().size() % d->colors.size()]); +  } +  else if (element && element->type() == Element::Range) +  { +    Range* range = static_cast<Range*>(element); +    range->setColor(d->colors[cells().size() % d->colors.size()]); +  } + +  d->activeElement = cells().begin(); + +  if (changedRegion == *this) +  { +    return; +  } +  changedRegion.add(TQRect(topLeft, bottomRight), sheet); + +  emit changed(changedRegion); +} + +void Selection::initialize(const Region& region, Sheet* sheet) +{ +    if (!region.isValid()) +        return; + +  if (!sheet) +  { +    if (d->sheet) +    { +      sheet = d->sheet; +    } +    else +    { +      sheet = d->view->activeSheet(); +    } +  } + +  Region changedRegion(*this); +  changedRegion.add(extendToMergedAreas(TQRect(d->anchor,d->marker))); + +  // TODO Stefan: handle subregion insertion +  // TODO Stefan: handle obscured cells correctly +  clear(); +  Element* element = add(region); +  if (element && element->type() == Element::Point) +  { +    Point* point = static_cast<Point*>(element); +    point->setColor(d->colors[cells().size() % d->colors.size()]); +  } +  else if (element && element->type() == Element::Range) +  { +    Range* range = static_cast<Range*>(element); +    range->setColor(d->colors[cells().size() % d->colors.size()]); +  } + +  TQPoint topLeft(cells().last()->rect().normalize().topLeft()); +  Cell* cell = d->view->activeSheet()->cellAt(topLeft); +  if (cell->isObscured() && cell->isPartOfMerged()) +  { +    cell = cell->obscuringCells().first(); +    topLeft = TQPoint(cell->column(), cell->row()); +  } + +  TQPoint bottomRight(cells().last()->rect().normalize().bottomRight()); +  cell = d->view->activeSheet()->cellAt(bottomRight); +  if (cell->isObscured() && cell->isPartOfMerged()) +  { +    cell = cell->obscuringCells().first(); +    bottomRight = TQPoint(cell->column(), cell->row()); +  } + +  d->anchor = topLeft; +  d->cursor = topLeft; +  d->marker = bottomRight; + +  d->activeElement = --cells().end(); +  d->activeSubRegionStart = 0; +  d->activeSubRegionLength = cells().count(); + +  if (changedRegion == *this) +  { +    return; +  } +  changedRegion.add( region ); + +  emit changed(changedRegion); +} + +void Selection::update() +{ +  emit changed(*this); +} + +void Selection::update(const TQPoint& point) +{ +  uint count = cells().count(); + +  if (cells().isEmpty()) +  { +    add(point); +    d->activeSubRegionLength += cells().count() - count; +    return; +  } +  if (d->activeElement == cells().end()) +  { +    // we're not empty, so this will not become again end() +    d->activeElement--; +  } + +  Sheet* sheet = (*d->activeElement)->sheet(); +  if (sheet != d->view->activeSheet()) +  { +    extend(point); +    d->activeSubRegionLength += cells().count() - count; +    return; +  } + +  TQPoint topLeft(point); +  Cell* cell = d->view->activeSheet()->cellAt(point); +  if (cell->isObscured() && cell->isPartOfMerged()) +  { +    cell = cell->obscuringCells().first(); +    topLeft = TQPoint(cell->column(), cell->row()); +  } + +  if (topLeft == d->marker) +  { +    return; +  } + +  TQRect area1 = (*d->activeElement)->rect().normalize(); +  TQRect newRange = extendToMergedAreas(TQRect(d->anchor, topLeft)); + +  Element* oldElement = *d->activeElement; +  // returns iterator to the next element or end +  Iterator it = cells().remove(d->activeElement); +  delete oldElement; +  // returns iterator to the new element (before 'it') or 'it' +  d->activeElement = insert(it, newRange, sheet, d->multipleSelection); +  d->activeSubRegionLength += cells().count() - count; + +  // The call to insert() above can just return the iterator which has been +  // passed in. This may be cells.end(), if the old active element was the +  // iterator to the list's end (!= last element). So attempts to dereference +  // it will fail. +  if (d->activeElement == cells().end()) +  { +    d->activeElement--; +  } + +  TQRect area2 = (*d->activeElement)->rect().normalize(); +  Region changedRegion; + +  bool newLeft   = area1.left() != area2.left(); +  bool newTop    = area1.top() != area2.top(); +  bool newRight  = area1.right() != area2.right(); +  bool newBottom = area1.bottom() != area2.bottom(); + +  /* first, calculate some numbers that we'll use a few times */ +  int farLeft = TQMIN(area1.left(), area2.left()); +  int innerLeft = TQMAX(area1.left(), area2.left()); + +  int farTop = TQMIN(area1.top(), area2.top()); +  int innerTop = TQMAX(area1.top(), area2.top()); + +  int farRight = TQMAX(area1.right(), area2.right()); +  int innerRight = TQMIN(area1.right(), area2.right()); + +  int farBottom = TQMAX(area1.bottom(), area2.bottom()); +  int innerBottom = TQMIN(area1.bottom(), area2.bottom()); + +  if (newLeft) +  { +    changedRegion.add(TQRect(TQPoint(farLeft, innerTop), +                      TQPoint(innerLeft-1, innerBottom))); +    if (newTop) +    { +      changedRegion.add(TQRect(TQPoint(farLeft, farTop), +                        TQPoint(innerLeft-1, innerTop-1))); +    } +    if (newBottom) +    { +      changedRegion.add(TQRect(TQPoint(farLeft, innerBottom+1), +                        TQPoint(innerLeft-1, farBottom))); +    } +  } + +  if (newTop) +  { +    changedRegion.add(TQRect(TQPoint(innerLeft, farTop), +                      TQPoint(innerRight, innerTop-1))); +  } + +  if (newRight) +  { +    changedRegion.add(TQRect(TQPoint(innerRight+1, innerTop), +                      TQPoint(farRight, innerBottom))); +    if (newTop) +    { +      changedRegion.add(TQRect(TQPoint(innerRight+1, farTop), +                        TQPoint(farRight, innerTop-1))); +    } +    if (newBottom) +    { +      changedRegion.add(TQRect(TQPoint(innerRight+1, innerBottom+1), +                        TQPoint(farRight, farBottom))); +    } +  } + +  if (newBottom) +  { +    changedRegion.add(TQRect(TQPoint(innerLeft, innerBottom+1), +                      TQPoint(innerRight, farBottom))); +  } + +  d->marker = topLeft; +  d->cursor = point; + +  emit changed(changedRegion); +} + +void Selection::extend(const TQPoint& point, Sheet* sheet) +{ +    if (!util_isPointValid(point)) +        return; + +  if (isEmpty()) +  { +    initialize(point, sheet); +    return; +  } +  if (d->activeElement == cells().end()) +  { +    // we're not empty, so this will not become again end() +    d->activeElement--; +  } + +  if (!sheet) +  { +    if (d->sheet) +    { +      sheet = d->sheet; +    } +    else +    { +      sheet = d->view->activeSheet(); +    } +  } + +  Region changedRegion = Region(extendToMergedAreas(TQRect(d->marker,d->marker))); + +  TQPoint topLeft(point); +  Cell* cell = d->view->activeSheet()->cellAt(point); +  if (cell->isObscured() && cell->isPartOfMerged()) +  { +    cell = cell->obscuringCells().first(); +    topLeft = TQPoint(cell->column(), cell->row()); +  } + +  uint count = cells().count(); +  if (d->multipleSelection) +  { +    d->activeElement = insert(++d->activeElement, point, sheet, false); +  } +  else +  { +    eor(topLeft, sheet); +    d->activeElement = --cells().end(); +  } +  d->anchor = (*d->activeElement)->rect().topLeft(); +  d->cursor = (*d->activeElement)->rect().bottomRight(); +  d->marker = d->cursor; + +  d->activeSubRegionLength += cells().count() - count; + +  changedRegion.add(topLeft, sheet); +  changedRegion.add(*this); + +  emit changed(changedRegion); +} + +void Selection::extend(const TQRect& range, Sheet* sheet) +{ +    //See comment in Selection::initialize(const TQRect& range, Sheet* sheet) +    if (!util_isRectValid(range) || (range == TQRect(0,0,1,1))) +        return; + +  if (isEmpty()) +  { +    initialize(range, sheet); +    return; +  } +  if (d->activeElement == cells().end()) +  { +    // we're not empty, so this will not become again end() +    d->activeElement--; +  } + +  if (!sheet) +  { +    if (d->sheet) +    { +      sheet = d->sheet; +    } +    else +    { +      sheet = d->view->activeSheet(); +    } +  } + +  TQPoint topLeft(range.topLeft()); +  Cell* cell = d->view->activeSheet()->cellAt(topLeft); +  if (cell->isObscured() && cell->isPartOfMerged()) +  { +    cell = cell->obscuringCells().first(); +    topLeft = TQPoint(cell->column(), cell->row()); +  } + +  TQPoint bottomRight(range.bottomRight()); +  cell = d->view->activeSheet()->cellAt(bottomRight); +  if (cell->isObscured() && cell->isPartOfMerged()) +  { +    cell = cell->obscuringCells().first(); +    bottomRight = TQPoint(cell->column(), cell->row()); +  } + +  d->anchor = topLeft; +  d->cursor = topLeft; +  d->marker = bottomRight; + +  uint count = cells().count(); +  Element* element; +  if (d->multipleSelection) +  { +    d->activeElement = insert(++d->activeElement, extendToMergedAreas(TQRect(topLeft, bottomRight)).normalize(), sheet, false); +    element = (d->activeElement == cells().end()) ? 0 : *d->activeElement; +  } +  else +  { +    element = add(extendToMergedAreas(TQRect(topLeft, bottomRight)).normalize(), sheet); +    d->activeElement = --cells().end(); +  } +  if (element && element->type() == Element::Point) +  { +    Point* point = static_cast<Point*>(element); +    point->setColor(d->colors[cells().size() % d->colors.size()]); +  } +  else if (element && element->type() == Element::Range) +  { +    Range* range = static_cast<Range*>(element); +    range->setColor(d->colors[cells().size() % d->colors.size()]); +  } + +  d->activeSubRegionLength += cells().count() - count; + +  emit changed(*this); +} + +void Selection::extend(const Region& region) +{ +    if (!region.isValid()) +        return; + +  uint count = cells().count(); +  ConstIterator end(region.constEnd()); +  for (ConstIterator it = region.constBegin(); it != end; ++it) +  { +    Element *element = *it; +    if (!element) continue; +    if (element->type() == Element::Point) +    { +      Point* point = static_cast<Point*>(element); +      extend(point->pos(), element->sheet()); +    } +    else +    { +      extend(element->rect(), element->sheet()); +    } +  } + +  d->activeSubRegionLength += cells().count() - count; + +  emit changed(*this); +} + +Selection::Element* Selection::eor(const TQPoint& point, Sheet* sheet) +{ +  if (isSingular()) +  { +    return Region::add(point, sheet); +  } +  return Region::eor(point, sheet); +} + +const TQPoint& Selection::anchor() const +{ +  return d->anchor; +} + +const TQPoint& Selection::cursor() const +{ +  return d->cursor; +} + +const TQPoint& Selection::marker() const +{ +  return d->marker; +} + +bool Selection::isSingular() const +{ +  return Region::isSingular(); +} + +TQRect Selection::selectionHandleArea() const +{ +  int column, row; + +  // complete rows/columns are selected, use the marker. +  if (isColumnOrRowSelected()) +  { +    column = d->marker.x(); +    row = d->marker.y(); +  } +  else +  { +    column = lastRange().right(); +    row = lastRange().bottom(); +  } +  const Cell* cell = d->view->activeSheet()->cellAt(column, row); + +  double xpos = d->view->activeSheet()->dblColumnPos( column ); +  double ypos = d->view->activeSheet()->dblRowPos( row ); +  double width = cell->dblWidth( column ); +  double height = cell->dblHeight( row ); + +  TQPoint rightBottom( d->view->doc()->zoomItX( xpos + width ), +                      d->view->doc()->zoomItY( ypos + height ) ); + +  TQRect handle( ( rightBottom.x() - 2 ), +                  ( rightBottom.y() - 2 ), +                  ( 5 ), +                  ( 5 ) ); +  return handle; +} + +TQString Selection::name(Sheet* sheet) const +{ +  return Region::name(sheet ? sheet : d->sheet); +} + +void Selection::setSheet(Sheet* sheet) +{ +  d->sheet = sheet; +} + +Sheet* Selection::sheet() const +{ +  return d->sheet; +} + +void Selection::setActiveElement(const TQPoint& point) +{ +  uint counter = 0; +  Iterator end = cells().end(); +  for (Iterator it = cells().begin(); it != end; ++it) +  { +    TQRect range = (*it)->rect(); +    if (range.topLeft() == point || range.bottomRight() == point) +    { +      d->anchor = range.topLeft(); +      d->cursor = range.bottomRight(); +      d->marker = range.bottomRight(); +      d->activeElement = it; +      d->activeSubRegionStart = counter; +      d->activeSubRegionLength = 1; +      if (d->view->canvasWidget()->editor()) +      { +        d->view->canvasWidget()->editor()->setCursorToRange(counter); +      } +    } +    counter++; +  } +} + +void Selection::setActiveElement(uint pos) +{ +  if (pos >= cells().count()) +  { +    kdDebug() << "Selection::setActiveElement: position exceeds list" << endl; +    d->activeElement = cells().begin(); +    return; +  } + +  Iterator it = cells().begin() += pos; +  TQRect range = (*it)->rect(); +  d->anchor = range.topLeft(); +  d->cursor = range.bottomRight(); +  d->marker = range.bottomRight(); +  d->activeElement = it; +} + +Region::Element* Selection::activeElement() const +{ +  return (d->activeElement == cells().end()) ? 0 : *d->activeElement; +} + +void Selection::clear() +{ +  d->activeSubRegionStart = 0; +  d->activeSubRegionLength = 0; +  Region::clear(); +  d->activeElement = cells().begin(); +} + +void Selection::clearSubRegion() +{ +  if (isEmpty()) +  { +    return; +  } +//   kdDebug() << *this << endl; +//   kdDebug() << d->activeSubRegionStart << endl; +//   kdDebug() << d->activeSubRegionLength << endl; + +  Iterator it = cells().begin(); +  Iterator end = it += d->activeSubRegionStart; +  end += d->activeSubRegionLength; +  while (it != end) +  { +/*    kdDebug() << (*it)->name() << endl;*/ +    delete *it; +    it = cells().remove(it); +  } +  d->activeSubRegionLength = 0; +  d->activeElement = it; +/*  kdDebug() << "ENDE" << endl;*/ +} + +void Selection::fixSubRegionDimension() +{ +  if (d->activeSubRegionStart > cells().count()) +  { +    kdDebug() << "Selection::fixSubRegionDimension: start position exceeds list" << endl; +    d->activeSubRegionStart = 0; +    d->activeSubRegionLength = cells().count(); +    return; +  } +  if (d->activeSubRegionStart + d->activeSubRegionLength > cells().count()) +  { +    kdDebug() << "Selection::fixSubRegionDimension: length exceeds list" << endl; +    d->activeSubRegionLength = cells().count() - d->activeSubRegionStart; +    return; +  } +} + +void Selection::setActiveSubRegion(uint start, uint length) +{ +//   kdDebug() << k_funcinfo << endl; +  d->activeSubRegionStart = start; +  d->activeSubRegionLength = length; +  fixSubRegionDimension(); +  d->activeElement = cells().begin() += d->activeSubRegionStart; +} + +TQString Selection::activeSubRegionName() const +{ +//   kdDebug() << k_funcinfo << endl; +//   kdDebug() << *this << endl; +//   kdDebug() << "start = " << d->activeSubRegionStart << ", len = " << d->activeSubRegionLength << endl; + +  TQStringList names; +  Iterator it = cells().begin(); +  it += d->activeSubRegionStart; +  Iterator end = it; +  end += d->activeSubRegionLength; +  while (it != end) +  { +    names += (*it++)->name(d->sheet); +  } +/*  kdDebug() << "ENDE" << endl;*/ +  return names.isEmpty() ? "" : names.join(";"); +} + +void Selection::setMultipleSelection(bool state) +{ +  d->multipleSelection = state; +} + +const TQValueList<TQColor>& Selection::colors() const +{ +  return d->colors; +} + +TQRect Selection::lastRange(bool extend) const +{ +  TQRect selection = TQRect(d->anchor, d->marker).normalize(); +  return extend ? extendToMergedAreas(selection) : selection; +} + +TQRect Selection::selection(bool extend) const +{ +  TQRect selection = TQRect(d->anchor, d->marker).normalize(); +  return extend ? extendToMergedAreas(selection) : selection; +} + +TQRect Selection::extendToMergedAreas(TQRect area) const +{ +  if (!d->view->activeSheet()) +	  return area; + +  area = area.normalize(); // TODO Stefan: avoid this +  const Cell *cell = d->view->activeSheet()->cellAt(area.left(), area.top()); + +  if( Region::Range(area).isColumn() || Region::Range(area).isRow() ) +  { +    return area; +  } +  else if ( !(cell->isObscured() && cell->isPartOfMerged()) && +              (cell->mergedXCells() + 1) >= area.width() && +              (cell->mergedYCells() + 1) >= area.height()) +  { +    /* if just a single cell is selected, we need to merge even when +    the obscuring isn't forced.  But only if this is the cell that +    is doing the obscuring -- we still want to be able to click on a cell +    that is being obscured. +    */ +    area.setWidth(cell->mergedXCells() + 1); +    area.setHeight(cell->mergedYCells() + 1); +  } +  else +  { +    int top=area.top(); +    int left=area.left(); +    int bottom=area.bottom(); +    int right=area.right(); +    for ( int x = area.left(); x <= area.right(); x++ ) +      for ( int y = area.top(); y <= area.bottom(); y++ ) +    { +      cell = d->view->activeSheet()->cellAt( x, y ); +      if( cell->doesMergeCells()) +      { +        right=TQMAX(right,cell->mergedXCells()+x); +        bottom=TQMAX(bottom,cell->mergedYCells()+y); +      } +      else if ( cell->isObscured() && cell->isPartOfMerged() ) +      { +        cell = cell->obscuringCells().first(); +        left=TQMIN(left,cell->column()); +        top=TQMIN(top,cell->row()); +        bottom=TQMAX(bottom,cell->row() + cell->mergedYCells()); +        right=TQMAX(right,cell->column() + cell->mergedXCells()); +      } +    } + +    area.setCoords(left,top,right,bottom); +  } +  return area; +} + +Selection::Region::Point* Selection::createPoint(const TQPoint& point) const +{ +  return new Point(point); +} + +Selection::Region::Point* Selection::createPoint(const TQString& string) const +{ +  return new Point(string); +} + +Selection::Region::Point* Selection::createPoint(const Point& point) const +{ +  return new Point(point); +} + +Selection::Region::Range* Selection::createRange(const TQRect& rect) const +{ +  return new Range(rect); +} + +Selection::Region::Range* Selection::createRange(const TQString& string) const +{ +  return new Range(string); +} + +Selection::Region::Range* Selection::createRange(const Range& range) const +{ +  return new Range(range); +} + +/*************************************************************************** +  class Point +****************************************************************************/ + +Selection::Point::Point(const TQPoint& point) +  : Region::Point(point), +    m_color(TQt::black), +    m_columnFixed(false), +    m_rowFixed(false) +{ +} + +Selection::Point::Point(const TQString& string) +  : Region::Point(string), +    m_color(TQt::black), +    m_columnFixed(false), +    m_rowFixed(false) +{ +  if (!isValid()) +  { +    return; +  } + +  uint p = 0; +  // Fixed? +  if (string[p++] == '$') +  { +    m_columnFixed = true; +  } + +  //search for the first character != text +  int result = string.find( TQRegExp("[^A-Za-z]+"), p ); +  if (string[result] == '$') +  { +    m_rowFixed = true; +  } +} + +/*************************************************************************** +  class Range +****************************************************************************/ + +Selection::Range::Range(const TQRect& range) +  : Region::Range(range), +    m_color(TQt::black), +    m_leftFixed(false), +    m_rightFixed(false), +    m_topFixed(false), +    m_bottomFixed(false) +{ +} + +Selection::Range::Range(const TQString& string) +  : Region::Range(string), +    m_color(TQt::black), +    m_leftFixed(false), +    m_rightFixed(false), +    m_topFixed(false), +    m_bottomFixed(false) +{ +  if (!isValid()) +  { +    return; +  } + +  int delimiterPos = string.find(':'); +  if (delimiterPos == -1) +  { +    return; +  } + +  Selection::Point ul(string.left(delimiterPos)); +  Selection::Point lr(string.mid(delimiterPos + 1)); + +  if (!ul.isValid() || !lr.isValid()) +  { +    return; +  } +  m_leftFixed = ul.columnFixed(); +  m_rightFixed = lr.columnFixed(); +  m_topFixed = ul.rowFixed(); +  m_bottomFixed = lr.rowFixed(); +} + +} // namespace KSpread +#include "selection.moc" | 
