KOffice – TDE office suite
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.

1010 lines
25KB

  1. /* This file is part of the KDE project
  2. Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
  3. Copyright (C) 2005-2006 Stefan Nikolaus <stefan.nikolaus@kdemail.net>
  4. This library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Library General Public
  6. License as published by the Free Software Foundation; either
  7. version 2 of the License, or (at your option) any later version.
  8. This library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Library General Public License for more details.
  12. You should have received a copy of the GNU Library General Public License
  13. along with this library; see the file COPYING.LIB. If not, write to
  14. the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  15. * Boston, MA 02110-1301, USA.
  16. */
  17. #include <tqregexp.h>
  18. #include <kdebug.h>
  19. #include "kspread_canvas.h"
  20. #include "kspread_cell.h"
  21. #include "kspread_doc.h"
  22. #include "kspread_editors.h"
  23. #include "kspread_sheet.h"
  24. #include "kspread_view.h"
  25. #include "kspread_util.h"
  26. #include "selection.h"
  27. // TODO Stefan: Substract points in selections
  28. // TODO Stefan: KPart signal (kspread_events.h)
  29. using namespace KSpread;
  30. /***************************************************************************
  31. class Selection::Private
  32. ****************************************************************************/
  33. class Selection::Private
  34. {
  35. public:
  36. Private(View *v)
  37. {
  38. view = v;
  39. sheet = 0;
  40. anchor = TQPoint(1,1);
  41. cursor = TQPoint(1,1);
  42. marker = TQPoint(1,1);
  43. colors.push_back(TQt::red);
  44. colors.push_back(TQt::blue);
  45. colors.push_back(TQt::magenta);
  46. colors.push_back(TQt::darkRed);
  47. colors.push_back(TQt::darkGreen);
  48. colors.push_back(TQt::darkMagenta);
  49. colors.push_back(TQt::darkCyan);
  50. colors.push_back(TQt::darkYellow);
  51. multipleSelection = false;
  52. activeElement = Iterator();
  53. activeSubRegionStart = 0;
  54. activeSubRegionLength = 0;
  55. }
  56. View* view;
  57. Sheet* sheet;
  58. TQPoint anchor;
  59. TQPoint cursor;
  60. TQPoint marker;
  61. TQValueList<TQColor> colors;
  62. bool multipleSelection : 1;
  63. Selection::Iterator activeElement;
  64. uint activeSubRegionStart;
  65. uint activeSubRegionLength;
  66. };
  67. /***************************************************************************
  68. class Selection
  69. ****************************************************************************/
  70. namespace KSpread {
  71. Selection::Selection(View *view)
  72. : TQObject(view), Region(1,1)
  73. {
  74. d = new Private(view);
  75. d->activeSubRegionStart = 0;
  76. d->activeSubRegionLength = 1;
  77. }
  78. Selection::Selection(const Selection& selection)
  79. : TQObject(selection.d->view), Region()
  80. {
  81. /* kdDebug() << k_funcinfo << endl;*/
  82. d = new Private(selection.d->view);
  83. d->sheet = selection.d->sheet;
  84. d->activeSubRegionStart = 0;
  85. d->activeSubRegionLength = cells().count();
  86. }
  87. Selection::~Selection()
  88. {
  89. delete d;
  90. }
  91. void Selection::initialize(const TQPoint& point, Sheet* sheet)
  92. {
  93. if (!util_isPointValid(point))
  94. return;
  95. if (!d->view->activeSheet())
  96. return;
  97. if (!sheet)
  98. {
  99. if (d->sheet)
  100. {
  101. sheet = d->sheet;
  102. }
  103. else
  104. {
  105. sheet = d->view->activeSheet();
  106. }
  107. }
  108. Region changedRegion(*this);
  109. changedRegion.add(extendToMergedAreas(TQRect(d->anchor,d->marker)));
  110. TQPoint topLeft(point);
  111. Cell* cell = d->view->activeSheet()->cellAt(point);
  112. if (cell->isObscured() && cell->isPartOfMerged())
  113. {
  114. cell = cell->obscuringCells().first();
  115. topLeft = TQPoint(cell->column(), cell->row());
  116. }
  117. d->anchor = topLeft;
  118. d->cursor = point;
  119. d->marker = topLeft;
  120. fixSubRegionDimension(); // TODO remove this sanity check
  121. Iterator it = cells().begin() += d->activeSubRegionStart + d->activeSubRegionLength;
  122. if (it != insert(it, topLeft, sheet/*, true*/))
  123. {
  124. // if the point was inserted
  125. clearSubRegion();
  126. }
  127. Element* element = *(cells().begin() += d->activeSubRegionStart);
  128. // we end up with one element in the subregion
  129. d->activeSubRegionLength = 1;
  130. if (element && element->type() == Element::Point)
  131. {
  132. Point* point = static_cast<Point*>(element);
  133. point->setColor(d->colors[cells().size() % d->colors.size()]);
  134. }
  135. else if (element && element->type() == Element::Range)
  136. {
  137. Range* range = static_cast<Range*>(element);
  138. range->setColor(d->colors[cells().size() % d->colors.size()]);
  139. }
  140. d->activeElement = cells().begin();
  141. if (changedRegion == *this)
  142. {
  143. emit changed(Region(topLeft, sheet));
  144. return;
  145. }
  146. changedRegion.add(topLeft, sheet);
  147. emit changed(changedRegion);
  148. }
  149. void Selection::initialize(const TQRect& range, Sheet* sheet)
  150. {
  151. if (!util_isRectValid(range) || ( range == TQRect(0,0,1,1) ))
  152. return;
  153. if (!sheet)
  154. {
  155. if (d->sheet)
  156. {
  157. sheet = d->sheet;
  158. }
  159. else
  160. {
  161. sheet = d->view->activeSheet();
  162. }
  163. }
  164. Region changedRegion(*this);
  165. changedRegion.add(extendToMergedAreas(TQRect(d->anchor,d->marker)));
  166. TQPoint topLeft(range.topLeft());
  167. Cell* cell = d->view->activeSheet()->cellAt(topLeft);
  168. if (cell->isObscured() && cell->isPartOfMerged())
  169. {
  170. cell = cell->obscuringCells().first();
  171. topLeft = TQPoint(cell->column(), cell->row());
  172. }
  173. TQPoint bottomRight(range.bottomRight());
  174. cell = d->view->activeSheet()->cellAt(bottomRight);
  175. if (cell->isObscured() && cell->isPartOfMerged())
  176. {
  177. cell = cell->obscuringCells().first();
  178. bottomRight = TQPoint(cell->column(), cell->row());
  179. }
  180. d->anchor = topLeft;
  181. d->cursor = bottomRight;
  182. d->marker = bottomRight;
  183. fixSubRegionDimension(); // TODO remove this sanity check
  184. Iterator it = cells().begin() += d->activeSubRegionStart + d->activeSubRegionLength;
  185. if (it != insert(it, TQRect(topLeft, bottomRight), sheet/*, true*/))
  186. {
  187. // if the range was inserted
  188. clearSubRegion();
  189. }
  190. Element* element = *(cells().begin() += d->activeSubRegionStart);
  191. // we end up with one element in the subregion
  192. d->activeSubRegionLength = 1;
  193. if (element && element->type() == Element::Point)
  194. {
  195. Point* point = static_cast<Point*>(element);
  196. point->setColor(d->colors[cells().size() % d->colors.size()]);
  197. }
  198. else if (element && element->type() == Element::Range)
  199. {
  200. Range* range = static_cast<Range*>(element);
  201. range->setColor(d->colors[cells().size() % d->colors.size()]);
  202. }
  203. d->activeElement = cells().begin();
  204. if (changedRegion == *this)
  205. {
  206. return;
  207. }
  208. changedRegion.add(TQRect(topLeft, bottomRight), sheet);
  209. emit changed(changedRegion);
  210. }
  211. void Selection::initialize(const Region& region, Sheet* sheet)
  212. {
  213. if (!region.isValid())
  214. return;
  215. if (!sheet)
  216. {
  217. if (d->sheet)
  218. {
  219. sheet = d->sheet;
  220. }
  221. else
  222. {
  223. sheet = d->view->activeSheet();
  224. }
  225. }
  226. Region changedRegion(*this);
  227. changedRegion.add(extendToMergedAreas(TQRect(d->anchor,d->marker)));
  228. // TODO Stefan: handle subregion insertion
  229. // TODO Stefan: handle obscured cells correctly
  230. clear();
  231. Element* element = add(region);
  232. if (element && element->type() == Element::Point)
  233. {
  234. Point* point = static_cast<Point*>(element);
  235. point->setColor(d->colors[cells().size() % d->colors.size()]);
  236. }
  237. else if (element && element->type() == Element::Range)
  238. {
  239. Range* range = static_cast<Range*>(element);
  240. range->setColor(d->colors[cells().size() % d->colors.size()]);
  241. }
  242. TQPoint topLeft(cells().last()->rect().normalize().topLeft());
  243. Cell* cell = d->view->activeSheet()->cellAt(topLeft);
  244. if (cell->isObscured() && cell->isPartOfMerged())
  245. {
  246. cell = cell->obscuringCells().first();
  247. topLeft = TQPoint(cell->column(), cell->row());
  248. }
  249. TQPoint bottomRight(cells().last()->rect().normalize().bottomRight());
  250. cell = d->view->activeSheet()->cellAt(bottomRight);
  251. if (cell->isObscured() && cell->isPartOfMerged())
  252. {
  253. cell = cell->obscuringCells().first();
  254. bottomRight = TQPoint(cell->column(), cell->row());
  255. }
  256. d->anchor = topLeft;
  257. d->cursor = topLeft;
  258. d->marker = bottomRight;
  259. d->activeElement = --cells().end();
  260. d->activeSubRegionStart = 0;
  261. d->activeSubRegionLength = cells().count();
  262. if (changedRegion == *this)
  263. {
  264. return;
  265. }
  266. changedRegion.add( region );
  267. emit changed(changedRegion);
  268. }
  269. void Selection::update()
  270. {
  271. emit changed(*this);
  272. }
  273. void Selection::update(const TQPoint& point)
  274. {
  275. uint count = cells().count();
  276. if (cells().isEmpty())
  277. {
  278. add(point);
  279. d->activeSubRegionLength += cells().count() - count;
  280. return;
  281. }
  282. if (d->activeElement == cells().end())
  283. {
  284. // we're not empty, so this will not become again end()
  285. d->activeElement--;
  286. }
  287. Sheet* sheet = (*d->activeElement)->sheet();
  288. if (sheet != d->view->activeSheet())
  289. {
  290. extend(point);
  291. d->activeSubRegionLength += cells().count() - count;
  292. return;
  293. }
  294. TQPoint topLeft(point);
  295. Cell* cell = d->view->activeSheet()->cellAt(point);
  296. if (cell->isObscured() && cell->isPartOfMerged())
  297. {
  298. cell = cell->obscuringCells().first();
  299. topLeft = TQPoint(cell->column(), cell->row());
  300. }
  301. if (topLeft == d->marker)
  302. {
  303. return;
  304. }
  305. TQRect area1 = (*d->activeElement)->rect().normalize();
  306. TQRect newRange = extendToMergedAreas(TQRect(d->anchor, topLeft));
  307. Element* oldElement = *d->activeElement;
  308. // returns iterator to the next element or end
  309. Iterator it = cells().remove(d->activeElement);
  310. delete oldElement;
  311. // returns iterator to the new element (before 'it') or 'it'
  312. d->activeElement = insert(it, newRange, sheet, d->multipleSelection);
  313. d->activeSubRegionLength += cells().count() - count;
  314. // The call to insert() above can just return the iterator which has been
  315. // passed in. This may be cells.end(), if the old active element was the
  316. // iterator to the list's end (!= last element). So attempts to dereference
  317. // it will fail.
  318. if (d->activeElement == cells().end())
  319. {
  320. d->activeElement--;
  321. }
  322. TQRect area2 = (*d->activeElement)->rect().normalize();
  323. Region changedRegion;
  324. bool newLeft = area1.left() != area2.left();
  325. bool newTop = area1.top() != area2.top();
  326. bool newRight = area1.right() != area2.right();
  327. bool newBottom = area1.bottom() != area2.bottom();
  328. /* first, calculate some numbers that we'll use a few times */
  329. int farLeft = TQMIN(area1.left(), area2.left());
  330. int innerLeft = TQMAX(area1.left(), area2.left());
  331. int farTop = TQMIN(area1.top(), area2.top());
  332. int innerTop = TQMAX(area1.top(), area2.top());
  333. int farRight = TQMAX(area1.right(), area2.right());
  334. int innerRight = TQMIN(area1.right(), area2.right());
  335. int farBottom = TQMAX(area1.bottom(), area2.bottom());
  336. int innerBottom = TQMIN(area1.bottom(), area2.bottom());
  337. if (newLeft)
  338. {
  339. changedRegion.add(TQRect(TQPoint(farLeft, innerTop),
  340. TQPoint(innerLeft-1, innerBottom)));
  341. if (newTop)
  342. {
  343. changedRegion.add(TQRect(TQPoint(farLeft, farTop),
  344. TQPoint(innerLeft-1, innerTop-1)));
  345. }
  346. if (newBottom)
  347. {
  348. changedRegion.add(TQRect(TQPoint(farLeft, innerBottom+1),
  349. TQPoint(innerLeft-1, farBottom)));
  350. }
  351. }
  352. if (newTop)
  353. {
  354. changedRegion.add(TQRect(TQPoint(innerLeft, farTop),
  355. TQPoint(innerRight, innerTop-1)));
  356. }
  357. if (newRight)
  358. {
  359. changedRegion.add(TQRect(TQPoint(innerRight+1, innerTop),
  360. TQPoint(farRight, innerBottom)));
  361. if (newTop)
  362. {
  363. changedRegion.add(TQRect(TQPoint(innerRight+1, farTop),
  364. TQPoint(farRight, innerTop-1)));
  365. }
  366. if (newBottom)
  367. {
  368. changedRegion.add(TQRect(TQPoint(innerRight+1, innerBottom+1),
  369. TQPoint(farRight, farBottom)));
  370. }
  371. }
  372. if (newBottom)
  373. {
  374. changedRegion.add(TQRect(TQPoint(innerLeft, innerBottom+1),
  375. TQPoint(innerRight, farBottom)));
  376. }
  377. d->marker = topLeft;
  378. d->cursor = point;
  379. emit changed(changedRegion);
  380. }
  381. void Selection::extend(const TQPoint& point, Sheet* sheet)
  382. {
  383. if (!util_isPointValid(point))
  384. return;
  385. if (isEmpty())
  386. {
  387. initialize(point, sheet);
  388. return;
  389. }
  390. if (d->activeElement == cells().end())
  391. {
  392. // we're not empty, so this will not become again end()
  393. d->activeElement--;
  394. }
  395. if (!sheet)
  396. {
  397. if (d->sheet)
  398. {
  399. sheet = d->sheet;
  400. }
  401. else
  402. {
  403. sheet = d->view->activeSheet();
  404. }
  405. }
  406. Region changedRegion = Region(extendToMergedAreas(TQRect(d->marker,d->marker)));
  407. TQPoint topLeft(point);
  408. Cell* cell = d->view->activeSheet()->cellAt(point);
  409. if (cell->isObscured() && cell->isPartOfMerged())
  410. {
  411. cell = cell->obscuringCells().first();
  412. topLeft = TQPoint(cell->column(), cell->row());
  413. }
  414. uint count = cells().count();
  415. if (d->multipleSelection)
  416. {
  417. d->activeElement = insert(++d->activeElement, point, sheet, false);
  418. }
  419. else
  420. {
  421. eor(topLeft, sheet);
  422. d->activeElement = --cells().end();
  423. }
  424. d->anchor = (*d->activeElement)->rect().topLeft();
  425. d->cursor = (*d->activeElement)->rect().bottomRight();
  426. d->marker = d->cursor;
  427. d->activeSubRegionLength += cells().count() - count;
  428. changedRegion.add(topLeft, sheet);
  429. changedRegion.add(*this);
  430. emit changed(changedRegion);
  431. }
  432. void Selection::extend(const TQRect& range, Sheet* sheet)
  433. {
  434. //See comment in Selection::initialize(const TQRect& range, Sheet* sheet)
  435. if (!util_isRectValid(range) || (range == TQRect(0,0,1,1)))
  436. return;
  437. if (isEmpty())
  438. {
  439. initialize(range, sheet);
  440. return;
  441. }
  442. if (d->activeElement == cells().end())
  443. {
  444. // we're not empty, so this will not become again end()
  445. d->activeElement--;
  446. }
  447. if (!sheet)
  448. {
  449. if (d->sheet)
  450. {
  451. sheet = d->sheet;
  452. }
  453. else
  454. {
  455. sheet = d->view->activeSheet();
  456. }
  457. }
  458. TQPoint topLeft(range.topLeft());
  459. Cell* cell = d->view->activeSheet()->cellAt(topLeft);
  460. if (cell->isObscured() && cell->isPartOfMerged())
  461. {
  462. cell = cell->obscuringCells().first();
  463. topLeft = TQPoint(cell->column(), cell->row());
  464. }
  465. TQPoint bottomRight(range.bottomRight());
  466. cell = d->view->activeSheet()->cellAt(bottomRight);
  467. if (cell->isObscured() && cell->isPartOfMerged())
  468. {
  469. cell = cell->obscuringCells().first();
  470. bottomRight = TQPoint(cell->column(), cell->row());
  471. }
  472. d->anchor = topLeft;
  473. d->cursor = topLeft;
  474. d->marker = bottomRight;
  475. uint count = cells().count();
  476. Element* element;
  477. if (d->multipleSelection)
  478. {
  479. d->activeElement = insert(++d->activeElement, extendToMergedAreas(TQRect(topLeft, bottomRight)).normalize(), sheet, false);
  480. element = (d->activeElement == cells().end()) ? 0 : *d->activeElement;
  481. }
  482. else
  483. {
  484. element = add(extendToMergedAreas(TQRect(topLeft, bottomRight)).normalize(), sheet);
  485. d->activeElement = --cells().end();
  486. }
  487. if (element && element->type() == Element::Point)
  488. {
  489. Point* point = static_cast<Point*>(element);
  490. point->setColor(d->colors[cells().size() % d->colors.size()]);
  491. }
  492. else if (element && element->type() == Element::Range)
  493. {
  494. Range* range = static_cast<Range*>(element);
  495. range->setColor(d->colors[cells().size() % d->colors.size()]);
  496. }
  497. d->activeSubRegionLength += cells().count() - count;
  498. emit changed(*this);
  499. }
  500. void Selection::extend(const Region& region)
  501. {
  502. if (!region.isValid())
  503. return;
  504. uint count = cells().count();
  505. ConstIterator end(region.constEnd());
  506. for (ConstIterator it = region.constBegin(); it != end; ++it)
  507. {
  508. Element *element = *it;
  509. if (!element) continue;
  510. if (element->type() == Element::Point)
  511. {
  512. Point* point = static_cast<Point*>(element);
  513. extend(point->pos(), element->sheet());
  514. }
  515. else
  516. {
  517. extend(element->rect(), element->sheet());
  518. }
  519. }
  520. d->activeSubRegionLength += cells().count() - count;
  521. emit changed(*this);
  522. }
  523. Selection::Element* Selection::eor(const TQPoint& point, Sheet* sheet)
  524. {
  525. if (isSingular())
  526. {
  527. return Region::add(point, sheet);
  528. }
  529. return Region::eor(point, sheet);
  530. }
  531. const TQPoint& Selection::anchor() const
  532. {
  533. return d->anchor;
  534. }
  535. const TQPoint& Selection::cursor() const
  536. {
  537. return d->cursor;
  538. }
  539. const TQPoint& Selection::marker() const
  540. {
  541. return d->marker;
  542. }
  543. bool Selection::isSingular() const
  544. {
  545. return Region::isSingular();
  546. }
  547. TQRect Selection::selectionHandleArea() const
  548. {
  549. int column, row;
  550. // complete rows/columns are selected, use the marker.
  551. if (isColumnOrRowSelected())
  552. {
  553. column = d->marker.x();
  554. row = d->marker.y();
  555. }
  556. else
  557. {
  558. column = lastRange().right();
  559. row = lastRange().bottom();
  560. }
  561. const Cell* cell = d->view->activeSheet()->cellAt(column, row);
  562. double xpos = d->view->activeSheet()->dblColumnPos( column );
  563. double ypos = d->view->activeSheet()->dblRowPos( row );
  564. double width = cell->dblWidth( column );
  565. double height = cell->dblHeight( row );
  566. TQPoint rightBottom( d->view->doc()->zoomItX( xpos + width ),
  567. d->view->doc()->zoomItY( ypos + height ) );
  568. TQRect handle( ( rightBottom.x() - 2 ),
  569. ( rightBottom.y() - 2 ),
  570. ( 5 ),
  571. ( 5 ) );
  572. return handle;
  573. }
  574. TQString Selection::name(Sheet* sheet) const
  575. {
  576. return Region::name(sheet ? sheet : d->sheet);
  577. }
  578. void Selection::setSheet(Sheet* sheet)
  579. {
  580. d->sheet = sheet;
  581. }
  582. Sheet* Selection::sheet() const
  583. {
  584. return d->sheet;
  585. }
  586. void Selection::setActiveElement(const TQPoint& point)
  587. {
  588. uint counter = 0;
  589. Iterator end = cells().end();
  590. for (Iterator it = cells().begin(); it != end; ++it)
  591. {
  592. TQRect range = (*it)->rect();
  593. if (range.topLeft() == point || range.bottomRight() == point)
  594. {
  595. d->anchor = range.topLeft();
  596. d->cursor = range.bottomRight();
  597. d->marker = range.bottomRight();
  598. d->activeElement = it;
  599. d->activeSubRegionStart = counter;
  600. d->activeSubRegionLength = 1;
  601. if (d->view->canvasWidget()->editor())
  602. {
  603. d->view->canvasWidget()->editor()->setCursorToRange(counter);
  604. }
  605. }
  606. counter++;
  607. }
  608. }
  609. void Selection::setActiveElement(uint pos)
  610. {
  611. if (pos >= cells().count())
  612. {
  613. kdDebug() << "Selection::setActiveElement: position exceeds list" << endl;
  614. d->activeElement = cells().begin();
  615. return;
  616. }
  617. Iterator it = cells().begin() += pos;
  618. TQRect range = (*it)->rect();
  619. d->anchor = range.topLeft();
  620. d->cursor = range.bottomRight();
  621. d->marker = range.bottomRight();
  622. d->activeElement = it;
  623. }
  624. Region::Element* Selection::activeElement() const
  625. {
  626. return (d->activeElement == cells().end()) ? 0 : *d->activeElement;
  627. }
  628. void Selection::clear()
  629. {
  630. d->activeSubRegionStart = 0;
  631. d->activeSubRegionLength = 0;
  632. Region::clear();
  633. d->activeElement = cells().begin();
  634. }
  635. void Selection::clearSubRegion()
  636. {
  637. if (isEmpty())
  638. {
  639. return;
  640. }
  641. // kdDebug() << *this << endl;
  642. // kdDebug() << d->activeSubRegionStart << endl;
  643. // kdDebug() << d->activeSubRegionLength << endl;
  644. Iterator it = cells().begin();
  645. Iterator end = it += d->activeSubRegionStart;
  646. end += d->activeSubRegionLength;
  647. while (it != end)
  648. {
  649. /* kdDebug() << (*it)->name() << endl;*/
  650. delete *it;
  651. it = cells().remove(it);
  652. }
  653. d->activeSubRegionLength = 0;
  654. d->activeElement = it;
  655. /* kdDebug() << "ENDE" << endl;*/
  656. }
  657. void Selection::fixSubRegionDimension()
  658. {
  659. if (d->activeSubRegionStart > cells().count())
  660. {
  661. kdDebug() << "Selection::fixSubRegionDimension: start position exceeds list" << endl;
  662. d->activeSubRegionStart = 0;
  663. d->activeSubRegionLength = cells().count();
  664. return;
  665. }
  666. if (d->activeSubRegionStart + d->activeSubRegionLength > cells().count())
  667. {
  668. kdDebug() << "Selection::fixSubRegionDimension: length exceeds list" << endl;
  669. d->activeSubRegionLength = cells().count() - d->activeSubRegionStart;
  670. return;
  671. }
  672. }
  673. void Selection::setActiveSubRegion(uint start, uint length)
  674. {
  675. // kdDebug() << k_funcinfo << endl;
  676. d->activeSubRegionStart = start;
  677. d->activeSubRegionLength = length;
  678. fixSubRegionDimension();
  679. d->activeElement = cells().begin() += d->activeSubRegionStart;
  680. }
  681. TQString Selection::activeSubRegionName() const
  682. {
  683. // kdDebug() << k_funcinfo << endl;
  684. // kdDebug() << *this << endl;
  685. // kdDebug() << "start = " << d->activeSubRegionStart << ", len = " << d->activeSubRegionLength << endl;
  686. TQStringList names;
  687. Iterator it = cells().begin();
  688. it += d->activeSubRegionStart;
  689. Iterator end = it;
  690. end += d->activeSubRegionLength;
  691. while (it != end)
  692. {
  693. names += (*it++)->name(d->sheet);
  694. }
  695. /* kdDebug() << "ENDE" << endl;*/
  696. return names.isEmpty() ? "" : names.join(";");
  697. }
  698. void Selection::setMultipleSelection(bool state)
  699. {
  700. d->multipleSelection = state;
  701. }
  702. const TQValueList<TQColor>& Selection::colors() const
  703. {
  704. return d->colors;
  705. }
  706. TQRect Selection::lastRange(bool extend) const
  707. {
  708. TQRect selection = TQRect(d->anchor, d->marker).normalize();
  709. return extend ? extendToMergedAreas(selection) : selection;
  710. }
  711. TQRect Selection::selection(bool extend) const
  712. {
  713. TQRect selection = TQRect(d->anchor, d->marker).normalize();
  714. return extend ? extendToMergedAreas(selection) : selection;
  715. }
  716. TQRect Selection::extendToMergedAreas(TQRect area) const
  717. {
  718. if (!d->view->activeSheet())
  719. return area;
  720. area = area.normalize(); // TODO Stefan: avoid this
  721. const Cell *cell = d->view->activeSheet()->cellAt(area.left(), area.top());
  722. if( Region::Range(area).isColumn() || Region::Range(area).isRow() )
  723. {
  724. return area;
  725. }
  726. else if ( !(cell->isObscured() && cell->isPartOfMerged()) &&
  727. (cell->mergedXCells() + 1) >= area.width() &&
  728. (cell->mergedYCells() + 1) >= area.height())
  729. {
  730. /* if just a single cell is selected, we need to merge even when
  731. the obscuring isn't forced. But only if this is the cell that
  732. is doing the obscuring -- we still want to be able to click on a cell
  733. that is being obscured.
  734. */
  735. area.setWidth(cell->mergedXCells() + 1);
  736. area.setHeight(cell->mergedYCells() + 1);
  737. }
  738. else
  739. {
  740. int top=area.top();
  741. int left=area.left();
  742. int bottom=area.bottom();
  743. int right=area.right();
  744. for ( int x = area.left(); x <= area.right(); x++ )
  745. for ( int y = area.top(); y <= area.bottom(); y++ )
  746. {
  747. cell = d->view->activeSheet()->cellAt( x, y );
  748. if( cell->doesMergeCells())
  749. {
  750. right=TQMAX(right,cell->mergedXCells()+x);
  751. bottom=TQMAX(bottom,cell->mergedYCells()+y);
  752. }
  753. else if ( cell->isObscured() && cell->isPartOfMerged() )
  754. {
  755. cell = cell->obscuringCells().first();
  756. left=TQMIN(left,cell->column());
  757. top=TQMIN(top,cell->row());
  758. bottom=TQMAX(bottom,cell->row() + cell->mergedYCells());
  759. right=TQMAX(right,cell->column() + cell->mergedXCells());
  760. }
  761. }
  762. area.setCoords(left,top,right,bottom);
  763. }
  764. return area;
  765. }
  766. Selection::Region::Point* Selection::createPoint(const TQPoint& point) const
  767. {
  768. return new Point(point);
  769. }
  770. Selection::Region::Point* Selection::createPoint(const TQString& string) const
  771. {
  772. return new Point(string);
  773. }
  774. Selection::Region::Point* Selection::createPoint(const Point& point) const
  775. {
  776. return new Point(point);
  777. }
  778. Selection::Region::Range* Selection::createRange(const TQRect& rect) const
  779. {
  780. return new Range(rect);
  781. }
  782. Selection::Region::Range* Selection::createRange(const TQString& string) const
  783. {
  784. return new Range(string);
  785. }
  786. Selection::Region::Range* Selection::createRange(const Range& range) const
  787. {
  788. return new Range(range);
  789. }
  790. /***************************************************************************
  791. class Point
  792. ****************************************************************************/
  793. Selection::Point::Point(const TQPoint& point)
  794. : Region::Point(point),
  795. m_color(TQt::black),
  796. m_columnFixed(false),
  797. m_rowFixed(false)
  798. {
  799. }
  800. Selection::Point::Point(const TQString& string)
  801. : Region::Point(string),
  802. m_color(TQt::black),
  803. m_columnFixed(false),
  804. m_rowFixed(false)
  805. {
  806. if (!isValid())
  807. {
  808. return;
  809. }
  810. uint p = 0;
  811. // Fixed?
  812. if (string[p++] == '$')
  813. {
  814. m_columnFixed = true;
  815. }
  816. //search for the first character != text
  817. int result = string.find( TQRegExp("[^A-Za-z]+"), p );
  818. if (string[result] == '$')
  819. {
  820. m_rowFixed = true;
  821. }
  822. }
  823. /***************************************************************************
  824. class Range
  825. ****************************************************************************/
  826. Selection::Range::Range(const TQRect& range)
  827. : Region::Range(range),
  828. m_color(TQt::black),
  829. m_leftFixed(false),
  830. m_rightFixed(false),
  831. m_topFixed(false),
  832. m_bottomFixed(false)
  833. {
  834. }
  835. Selection::Range::Range(const TQString& string)
  836. : Region::Range(string),
  837. m_color(TQt::black),
  838. m_leftFixed(false),
  839. m_rightFixed(false),
  840. m_topFixed(false),
  841. m_bottomFixed(false)
  842. {
  843. if (!isValid())
  844. {
  845. return;
  846. }
  847. int delimiterPos = string.find(':');
  848. if (delimiterPos == -1)
  849. {
  850. return;
  851. }
  852. Selection::Point ul(string.left(delimiterPos));
  853. Selection::Point lr(string.mid(delimiterPos + 1));
  854. if (!ul.isValid() || !lr.isValid())
  855. {
  856. return;
  857. }
  858. m_leftFixed = ul.columnFixed();
  859. m_rightFixed = lr.columnFixed();
  860. m_topFixed = ul.rowFixed();
  861. m_bottomFixed = lr.rowFixed();
  862. }
  863. } // namespace KSpread
  864. #include "selection.moc"