xref: /aoo41x/main/sc/source/ui/view/tabvwsh5.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sc.hxx"
30 
31 
32 
33 // INCLUDE ---------------------------------------------------------------
34 #define _ZFORLIST_DECLARE_TABLE
35 #include "scitems.hxx"
36 #include <svl/smplhint.hxx>
37 #include <svl/zforlist.hxx>
38 #include <svx/numfmtsh.hxx>
39 #include <svx/numinf.hxx>
40 #include <svx/svxids.hrc>
41 #include <sfx2/dispatch.hxx>
42 #include <sfx2/objsh.hxx>
43 
44 #include "tabvwsh.hxx"
45 #include "sc.hrc"
46 #include "global.hxx"
47 #include "docsh.hxx"
48 #include "document.hxx"
49 #include "cell.hxx"
50 #include "globstr.hrc"
51 #include "scmod.hxx"
52 #include "uiitems.hxx"
53 #include "editsh.hxx"
54 #include "hints.hxx"
55 
56 
57 //==================================================================
58 
59 void __EXPORT ScTabViewShell::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
60 {
61 	if (rHint.ISA(SfxSimpleHint))						// ohne Parameter
62 	{
63 		sal_uLong nSlot = ((SfxSimpleHint&)rHint).GetId();
64 		switch ( nSlot )
65 		{
66 			case FID_DATACHANGED:
67 				UpdateFormulas();
68 				break;
69 
70 			case FID_REFMODECHANGED:
71 				{
72 					sal_Bool bRefMode = SC_MOD()->IsFormulaMode();
73 					if (!bRefMode)
74 						StopRefMode();
75 					else
76 					{
77 						GetSelEngine()->Reset();
78 						GetFunctionSet()->SetAnchorFlag(sal_True);
79 						//	AnchorFlag, damit gleich mit Control angehaengt werden kann
80 					}
81 				}
82 				break;
83 
84 			case FID_KILLEDITVIEW:
85 			case FID_KILLEDITVIEW_NOPAINT:
86 				StopEditShell();
87 				KillEditView( nSlot == FID_KILLEDITVIEW_NOPAINT );
88 				break;
89 
90 			case SFX_HINT_DOCCHANGED:
91 				{
92 					ScDocument* pDoc = GetViewData()->GetDocument();
93 					if (!pDoc->HasTable( GetViewData()->GetTabNo() ))
94 					{
95 						SetTabNo(0);
96 					}
97 				}
98 				break;
99 
100 			case SC_HINT_DRWLAYER_NEW:
101 				MakeDrawView();
102 				break;
103 
104 			case SC_HINT_DOC_SAVED:
105 				{
106 					//	beim "Save as" kann ein vorher schreibgeschuetztes Dokument
107 					//	bearbeitbar werden, deshalb die Layer-Locks neu (#39884#)
108 					//	(Invalidate etc. passiert schon vom Sfx her)
109 					//	#42091# bei SID_EDITDOC kommt kein SFX_HINT_TITLECHANGED, darum
110 					//	der eigene Hint aus DoSaveCompleted
111 					//!	was ist mit SFX_HINT_SAVECOMPLETED ?
112 
113 					UpdateLayerLocks();
114 
115 					//	#54891# Design-Modus bei jedem Speichern anzupassen, waere zuviel
116 					//	(beim Speichern unter gleichem Namen soll er unveraendert bleiben)
117 					//	Darum nur bei SFX_HINT_MODECHANGED (vom ViewFrame)
118 				}
119 				break;
120 
121 			case SFX_HINT_MODECHANGED:
122 				//	#54891#/#58510# Da man sich nicht mehr darauf verlassen kann, woher
123 				//	dieser Hint kommt, den Design-Modus immer dann umschalten, wenn der
124 				//	ReadOnly-Status sich wirklich geaendert hat:
125 
126 				if ( GetViewData()->GetSfxDocShell()->IsReadOnly() != bReadOnly )
127 				{
128 					bReadOnly = GetViewData()->GetSfxDocShell()->IsReadOnly();
129 
130 					SfxBoolItem aItem( SID_FM_DESIGN_MODE, !bReadOnly);
131 					GetViewData()->GetDispatcher().Execute( SID_FM_DESIGN_MODE, SFX_CALLMODE_ASYNCHRON,
132 												&aItem, 0L );
133 
134 					UpdateInputContext();
135 				}
136 				break;
137 
138 			case SC_HINT_SHOWRANGEFINDER:
139 				PaintRangeFinder();
140 				break;
141 
142 			case SC_HINT_FORCESETTAB:
143 				SetTabNo( GetViewData()->GetTabNo(), sal_True );
144 				break;
145 
146 			default:
147 				break;
148 		}
149 	}
150 	else if (rHint.ISA(ScPaintHint))					// neu zeichnen
151 	{
152 		ScPaintHint* pHint = (ScPaintHint*) &rHint;
153 		sal_uInt16 nParts = pHint->GetParts();
154 		SCTAB nTab = GetViewData()->GetTabNo();
155 		if (pHint->GetStartTab() <= nTab && pHint->GetEndTab() >= nTab)
156 		{
157 			if (nParts & PAINT_EXTRAS)			// zuerst, falls Tabelle weg ist !!!
158 				if (PaintExtras())
159 					nParts = PAINT_ALL;
160 
161             // if the current sheet has pending row height updates (sheet links refreshed),
162             // execute them before invalidating the window
163             GetViewData()->GetDocShell()->UpdatePendingRowHeights( GetViewData()->GetTabNo() );
164 
165 			if (nParts & PAINT_SIZE)
166 				RepeatResize(); 					//! InvalidateBorder ???
167 			if (nParts & PAINT_GRID)
168 				PaintArea( pHint->GetStartCol(), pHint->GetStartRow(),
169 						   pHint->GetEndCol(), pHint->GetEndRow() );
170 			if (nParts & PAINT_MARKS)
171 				PaintArea( pHint->GetStartCol(), pHint->GetStartRow(),
172 						   pHint->GetEndCol(), pHint->GetEndRow(), SC_UPDATE_MARKS );
173 			if (nParts & PAINT_LEFT)
174 				PaintLeftArea( pHint->GetStartRow(), pHint->GetEndRow() );
175 			if (nParts & PAINT_TOP)
176 				PaintTopArea( pHint->GetStartCol(), pHint->GetEndCol() );
177 			if (nParts & PAINT_INVERT)
178 				InvertBlockMark( pHint->GetStartCol(), pHint->GetStartRow(),
179 								 pHint->GetEndCol(), pHint->GetEndRow() );
180 
181             // #i84689# call UpdateAllOverlays here instead of in ScTabView::PaintArea
182             if (nParts & ( PAINT_LEFT | PAINT_TOP ))    // only if widths or heights changed
183                 UpdateAllOverlays();
184 
185 			HideNoteMarker();
186 		}
187 	}
188 	else if (rHint.ISA(ScEditViewHint))					// Edit-View anlegen
189 	{
190 		//	ScEditViewHint kommt nur an aktiver View an
191 
192 		ScEditViewHint* pHint = (ScEditViewHint*) &rHint;
193 		SCTAB nTab = GetViewData()->GetTabNo();
194 		if ( pHint->GetTab() == nTab )
195 		{
196 			SCCOL nCol = pHint->GetCol();
197 			SCROW nRow = pHint->GetRow();
198 			{
199 				HideNoteMarker();
200 
201 				MakeEditView( pHint->GetEngine(), nCol, nRow );
202 
203 				StopEditShell();					// sollte nicht gesetzt sein
204 
205 				ScSplitPos eActive = GetViewData()->GetActivePart();
206 				if ( GetViewData()->HasEditView(eActive) )
207 				{
208 					//	MakeEditView geht schief, wenn der Cursor ausserhalb des
209 					//	Bildschirms steht. GetEditView gibt dann eine nicht aktive
210 					//	View zurueck, darum die Abfrage HasEditView.
211 
212 					EditView* pView = GetViewData()->GetEditView(eActive);	// ist nicht 0
213 
214 					SetEditShell(pView ,sal_True);
215 				}
216 			}
217 		}
218 	}
219 	else if (rHint.ISA(ScTablesHint))				// Tabelle eingefuegt / geloescht
220 	{
221 			//	aktuelle Tabelle zuerst holen (kann bei DeleteTab an ViewData geaendert werden)
222 		SCTAB nActiveTab = GetViewData()->GetTabNo();
223 
224 		const ScTablesHint& rTabHint = (const ScTablesHint&)rHint;
225 		SCTAB nTab1 = rTabHint.GetTab1();
226 		SCTAB nTab2 = rTabHint.GetTab2();
227 		sal_uInt16 nId  = rTabHint.GetId();
228 		switch (nId)
229 		{
230 			case SC_TAB_INSERTED:
231 				GetViewData()->InsertTab( nTab1 );
232 				break;
233 			case SC_TAB_DELETED:
234 				GetViewData()->DeleteTab( nTab1 );
235 				break;
236 			case SC_TAB_MOVED:
237 				GetViewData()->MoveTab( nTab1, nTab2 );
238 				break;
239 			case SC_TAB_COPIED:
240 				GetViewData()->CopyTab( nTab1, nTab2 );
241 				break;
242 			case SC_TAB_HIDDEN:
243 				break;
244 			default:
245 				DBG_ERROR("unbekannter ScTablesHint");
246 		}
247 
248 		//	hier keine Abfrage auf IsActive() mehr, weil die Aktion von Basic ausgehen
249 		//	kann und dann auch die aktive View umgeschaltet werden muss.
250 
251 		SCTAB nNewTab = nActiveTab;
252 		bool bStayOnActiveTab = true;
253 		switch (nId)
254 		{
255 			case SC_TAB_INSERTED:
256 				if ( nTab1 <= nNewTab )				// vorher eingefuegt
257 					++nNewTab;
258 				break;
259 			case SC_TAB_DELETED:
260 				if ( nTab1 < nNewTab )				// vorher geloescht
261 					--nNewTab;
262 				else if ( nTab1 == nNewTab )		// aktuelle geloescht
263 					bStayOnActiveTab = false;
264 				break;
265 			case SC_TAB_MOVED:
266 				if ( nNewTab == nTab1 )				// verschobene Tabelle
267 					nNewTab = nTab2;
268 				else if ( nTab1 < nTab2 )			// nach hinten verschoben
269 				{
270 					if ( nNewTab > nTab1 && nNewTab <= nTab2 )		// nachrueckender Bereich
271 						--nNewTab;
272 				}
273 				else								// nach vorne verschoben
274 				{
275 					if ( nNewTab >= nTab2 && nNewTab < nTab1 )		// nachrueckender Bereich
276 						++nNewTab;
277 				}
278 				break;
279 			case SC_TAB_COPIED:
280 				if ( nNewTab >= nTab2 )				// vorher eingefuegt
281 					++nNewTab;
282 				break;
283 			case SC_TAB_HIDDEN:
284 				if ( nTab1 == nNewTab )				// aktuelle ausgeblendet
285 					bStayOnActiveTab = false;
286 				break;
287 		}
288 
289 		ScDocument* pDoc = GetViewData()->GetDocument();
290 		if ( nNewTab >= pDoc->GetTableCount() )
291 			nNewTab = pDoc->GetTableCount() - 1;
292 
293         sal_Bool bForce = !bStayOnActiveTab;
294 		SetTabNo( nNewTab, bForce, sal_False, bStayOnActiveTab );
295 	}
296 	else if (rHint.ISA(ScIndexHint))
297 	{
298 		const ScIndexHint& rIndexHint = (const ScIndexHint&)rHint;
299 		sal_uInt16 nId = rIndexHint.GetId();
300 		sal_uInt16 nIndex = rIndexHint.GetIndex();
301 		switch (nId)
302 		{
303 			case SC_HINT_SHOWRANGEFINDER:
304 				PaintRangeFinder( nIndex );
305 				break;
306 		}
307 	}
308 
309 	SfxViewShell::Notify( rBC, rHint );
310 }
311 
312 //------------------------------------------------------------------
313 
314 void ScTabViewShell::MakeNumberInfoItem( ScDocument*		 pDoc,
315 										 ScViewData*		 pViewData,
316 										 SvxNumberInfoItem** ppItem )
317 {
318 	//------------------------------
319 	// NumberInfo-Item konstruieren:
320 	//------------------------------
321 	ScBaseCell* 		pCell = NULL;
322 	SvxNumberValueType	eValType		= SVX_VALUE_TYPE_UNDEFINED;
323 	double				nCellValue		= 0;
324 	String				aCellString;
325 
326 	pDoc->GetCell( pViewData->GetCurX(),
327 				   pViewData->GetCurY(),
328 				   pViewData->GetTabNo(),
329 				   pCell );
330 
331 	if ( pCell )
332 	{
333 		switch ( pCell->GetCellType() )
334 		{
335 			case CELLTYPE_VALUE:
336 				{
337 					nCellValue = ((ScValueCell*)pCell)->GetValue();
338 					eValType = SVX_VALUE_TYPE_NUMBER;
339 					aCellString.Erase();
340 				}
341 				break;
342 
343 			case CELLTYPE_STRING:
344 				{
345 					((ScStringCell*)pCell)->GetString( aCellString );
346 					eValType = SVX_VALUE_TYPE_STRING;
347 				}
348 				break;
349 
350 			case CELLTYPE_FORMULA:
351 				{
352 					if ( ((ScFormulaCell*)pCell)->IsValue() )
353 					{
354 						nCellValue = ((ScFormulaCell*)pCell)->GetValue();
355 						eValType = SVX_VALUE_TYPE_NUMBER;
356 					}
357 					else
358 					{
359 						nCellValue = 0;
360 						eValType   = SVX_VALUE_TYPE_UNDEFINED;
361 					}
362 					aCellString.Erase();
363 				}
364 				break;
365 
366 			default:
367 				nCellValue = 0;
368 				eValType   = SVX_VALUE_TYPE_UNDEFINED;
369 				aCellString.Erase();
370 		}
371 	}
372 	else // Zelle noch leer (== nicht erzeugt)
373 	{
374 		nCellValue = 0;
375 		eValType   = SVX_VALUE_TYPE_UNDEFINED;
376 		aCellString.Erase();
377 	}
378 
379 	switch ( eValType )
380 	{
381 		case SVX_VALUE_TYPE_STRING:
382 			*ppItem = new SvxNumberInfoItem(
383 								pDoc->GetFormatTable(),
384 								aCellString,
385 								SID_ATTR_NUMBERFORMAT_INFO );
386 			break;
387 
388 		case SVX_VALUE_TYPE_NUMBER:
389 			*ppItem = new SvxNumberInfoItem(
390 								pDoc->GetFormatTable(),
391 								nCellValue,
392 								SID_ATTR_NUMBERFORMAT_INFO );
393 			break;
394 
395 		case SVX_VALUE_TYPE_UNDEFINED:
396 		default:
397 			*ppItem = new SvxNumberInfoItem(
398 								pDoc->GetFormatTable(),
399 								(const sal_uInt16)
400 								SID_ATTR_NUMBERFORMAT_INFO );
401 	}
402 }
403 
404 //------------------------------------------------------------------
405 
406 void ScTabViewShell::UpdateNumberFormatter(
407 						ScDocument* 			 pDoc,
408 						const SvxNumberInfoItem& rInfoItem )
409 {
410 	const sal_uInt32 nDelCount = rInfoItem.GetDelCount();
411 
412 	if ( nDelCount > 0 )
413 	{
414 		const sal_uInt32* pDelArr = rInfoItem.GetDelArray();
415 
416 		for ( sal_uInt16 i=0; i<nDelCount; i++ )
417 			rInfoItem.GetNumberFormatter()->DeleteEntry( pDelArr[i] );
418 	}
419 
420 	// sollte besser UpdateNumberFormats() heissen ?
421 	pDoc->DeleteNumberFormat( rInfoItem.GetDelArray(),
422 							  rInfoItem.GetDelCount() );
423 }
424 
425 
426 
427 
428 
429 
430