1
/* This file is part of the KDE project
2
Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
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.
9
This library is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
Library General Public License for more details.
14
You should have received a copy of the GNU Library General Public License
15
along with this library; see the file COPYING.LIB. If not, write to
16
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17
Boston, MA 02111-1307, USA.
20
#include "kspread_selection.h"
21
#include "kspread_canvas.h"
22
#include "kspread_cell.h"
23
#include "kspread_global.h"
24
#include "kspread_sheet.h"
25
#include "kspread_view.h"
27
KSpreadSelection::KSpreadSelection(KSpreadView* view)
29
m_marker = QPoint(1,1);
30
m_cursorPosition = QPoint(1,1);
31
m_anchor = QPoint(1,1);
33
m_chooseMarker = QPoint(0,0);
34
m_chooseAnchor = QPoint(0,0);
35
m_chooseCursor = QPoint(0,0);
41
KSpreadSelection::~KSpreadSelection()
45
/******************************************
46
* Functions dealing with the current selection
49
void KSpreadSelection::unselect()
51
// No selection? Then do nothing.
52
if ( singleCellSelection() )
55
QRect r = m_rctSelection;
56
// Discard the selection
57
KSpreadCell *cell = cellAt(marker());
58
m_rctSelection.setCoords( m_marker.x(), m_marker.y(),
59
m_marker.x() + cell->extraXCells(),
60
m_marker.y() + cell->extraYCells() );
62
// Emit signal so that the views can update.
63
// emit sig_unselect( this, r );
67
QPoint KSpreadSelection::marker() const
72
QRect KSpreadSelection::selection() const
74
int left, top, right, bottom;
75
left = QMIN(m_anchor.x(), m_marker.x());
76
top = QMIN(m_anchor.y(), m_marker.y());
77
right = QMAX(m_anchor.x(), m_marker.x());
78
bottom = QMAX(m_anchor.y(), m_marker.y());
79
QRect selection(QPoint(left, top), QPoint(right, bottom));
81
return extendToMergedAreas(selection);
84
bool KSpreadSelection::singleCellSelection() const
86
const KSpreadCell* cell =
87
m_pView->activeTable()->cellAt(m_marker.x(), m_marker.y());
89
QRect currentSelection = selection();
90
return ((currentSelection.topLeft() == m_marker) &&
91
(currentSelection.width() - 1 == cell->extraXCells()) &&
92
(currentSelection.height() - 1 == cell->extraYCells()));
95
QRect KSpreadSelection::selectionHandleArea() const
99
// complete rows/columns are selected, use the marker.
100
if ( util_isRowSelected(selection()) ||
101
util_isColumnSelected(selection()) )
103
column = marker().x();
108
column = selection().right();
109
row = selection().bottom();
111
const KSpreadCell* cell = m_pView->activeTable()->cellAt(column, row);
113
double xpos = m_pView->activeTable()->dblColumnPos( column );
114
double ypos = m_pView->activeTable()->dblRowPos( row );
115
double width = cell->dblWidth( column );
116
double height = cell->dblHeight( row );
118
QPoint rightBottom( m_pView->doc()->zoomItX( xpos + width ),
119
m_pView->doc()->zoomItY( ypos + height ) );
121
QRect handle( ( rightBottom.x() - 2 ),
122
( rightBottom.y() - 2 ),
128
void KSpreadSelection::setSelection( const QPoint &newMarker,
129
const QPoint &newAnchor,
130
KSpreadSheet *table )
132
QRect oldSelection = selection();
133
QPoint oldMarker = m_marker;
134
m_marker = newMarker;
135
m_anchor = newAnchor;
137
QRect newSelection = selection();
139
const KSpreadCell* cell = table->cellAt(newMarker);
140
if (!util_isColumnSelected(newSelection) &&
141
!util_isRowSelected(newSelection) &&
142
cell->isObscured() && cell->isObscuringForced())
144
cell = cell->obscuringCells().first();
145
m_marker = QPoint(cell->column(), cell->row());
148
newSelection = selection();
150
/* see if we've actually changed anything */
151
if ( newSelection == oldSelection && newMarker == oldMarker &&
152
m_pView->activeTable() == table )
155
/* see if the cursor position is still valid */
156
if (!setCursorPosition(m_cursorPosition))
158
setCursorPosition(newMarker);
161
m_pView->enableInsertColumn( !util_isRowSelected( newSelection ) );
162
m_pView->enableInsertRow( !util_isColumnSelected( newSelection ) );
163
m_pView->slotChangeSelection( table, oldSelection, oldMarker );
166
void KSpreadSelection::setMarker( const QPoint &point,
167
KSpreadSheet* table )
169
QPoint topLeft(point);
170
const KSpreadCell* cell = table->cellAt(topLeft);
171
if (cell->isObscured() && cell->isObscuringForced())
173
cell = cell->obscuringCells().first();
174
topLeft = QPoint(cell->column(), cell->row());
177
QPoint botRight(topLeft.x() + cell->extraXCells(),
178
topLeft.y() + cell->extraYCells());
179
setSelection( topLeft, botRight, table );
182
QPoint KSpreadSelection::selectionAnchor()const
185
/* the anchor is in the opposite corner of the selection rect from the marker */
187
/* these show where the marker is */
193
atLeft = m_marker.x() == m_rctSelection.left();
194
atTop = m_marker.y() == m_rctSelection.top();
196
QPoint anchor(atLeft ? m_rctSelection.right() : m_rctSelection.left(),
197
atTop ? m_rctSelection.bottom() : m_rctSelection.top());
199
KSpreadSheet* table = m_pView->activeTable();
200
KSpreadCell* cell = table->cellAt(anchor);
202
if (cell->isObscured())
204
cell = cell->obscuringCells().first();
205
anchorArea = QRect(QPoint(cell->column(), cell->row()), anchor);
209
anchorArea = QRect(anchor, anchor);
216
bool KSpreadSelection::setCursorPosition( const QPoint &position )
218
const KSpreadCell* cell = m_pView->activeTable()->cellAt(m_marker);
220
QRect markerArea(m_marker, QPoint(m_marker.x() + cell->mergedXCells(),
221
m_marker.y() + cell->mergedYCells()));
223
if (markerArea.contains(position))
225
m_cursorPosition = position;
231
QPoint KSpreadSelection::cursorPosition()const
233
return m_cursorPosition;
236
QRect KSpreadSelection::getChooseRect()const
240
chooseRect.setLeft(QMIN(m_chooseMarker.x(), m_chooseAnchor.x()));
241
chooseRect.setRight(QMAX(m_chooseMarker.x(), m_chooseAnchor.x()));
242
chooseRect.setTop(QMIN(m_chooseMarker.y(), m_chooseAnchor.y()));
243
chooseRect.setBottom(QMAX(m_chooseMarker.y(), m_chooseAnchor.y()));
250
QRect KSpreadSelection::extendToMergedAreas(QRect area) const
252
const KSpreadCell *cell = m_pView->activeTable()->
253
cellAt(area.left(), area.top());
255
if( util_isColumnSelected(area) ||
256
util_isRowSelected(area) )
259
else if ( !(cell->isObscured() && cell->isObscuringForced()) &&
260
(cell->extraXCells() + 1) >= area.width() &&
261
(cell->extraYCells() + 1) >= area.height())
263
/* if just a single cell is selected, we need to merge even when
264
the obscuring isn't forced. But only if this is the cell that
265
is doing the obscuring -- we still want to be able to click on a cell
266
that is being obscured.
268
area.setWidth(cell->extraXCells() + 1);
269
area.setHeight(cell->extraYCells() + 1);
274
int left=area.left();
275
int bottom=area.bottom();
276
int right=area.right();
277
for ( int x = area.left(); x <= area.right(); x++ )
278
for ( int y = area.top(); y <= area.bottom(); y++ )
280
cell = m_pView->activeTable()->cellAt( x, y );
281
if( cell->isForceExtraCells())
283
right=QMAX(right,cell->extraXCells()+x);
284
bottom=QMAX(bottom,cell->extraYCells()+y);
286
else if ( cell->isObscured() && cell->isObscuringForced() )
288
cell = cell->obscuringCells().first();
289
left=QMIN(left,cell->column());
290
top=QMIN(top,cell->row());
291
bottom=QMAX(bottom,cell->row() + cell->extraYCells());
292
right=QMAX(right,cell->column() + cell->extraXCells());
296
area.setCoords(left,top,right,bottom);