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 #include "oox/xls/viewsettings.hxx" 29 30 #include <com/sun/star/awt/Point.hpp> 31 #include <com/sun/star/awt/Size.hpp> 32 #include <com/sun/star/beans/PropertyValue.hpp> 33 #include <com/sun/star/container/XIndexContainer.hpp> 34 #include <com/sun/star/container/XNameContainer.hpp> 35 #include <com/sun/star/document/XViewDataSupplier.hpp> 36 #include <comphelper/mediadescriptor.hxx> 37 #include "oox/core/filterbase.hxx" 38 #include "oox/helper/attributelist.hxx" 39 #include "oox/helper/containerhelper.hxx" 40 #include "oox/helper/propertymap.hxx" 41 #include "oox/helper/propertyset.hxx" 42 #include "oox/xls/addressconverter.hxx" 43 #include "oox/xls/biffinputstream.hxx" 44 #include "oox/xls/unitconverter.hxx" 45 #include "oox/xls/workbooksettings.hxx" 46 #include "oox/xls/worksheetbuffer.hxx" 47 48 namespace oox { 49 namespace xls { 50 51 // ============================================================================ 52 53 using namespace ::com::sun::star::awt; 54 using namespace ::com::sun::star::container; 55 using namespace ::com::sun::star::document; 56 using namespace ::com::sun::star::table; 57 using namespace ::com::sun::star::uno; 58 59 using ::oox::core::FilterBase; 60 using ::rtl::OUString; 61 62 // ============================================================================ 63 64 namespace { 65 66 const sal_Int32 OOX_BOOKVIEW_TABBARRATIO_DEF = 600; /// Default tabbar ratio. 67 const sal_Int32 OOX_SHEETVIEW_NORMALZOOM_DEF = 100; /// Default zoom for normal view. 68 const sal_Int32 OOX_SHEETVIEW_SHEETLAYZOOM_DEF = 60; /// Default zoom for pagebreak preview. 69 const sal_Int32 OOX_SHEETVIEW_PAGELAYZOOM_DEF = 100; /// Default zoom for page layout view. 70 71 const sal_uInt8 BIFF12_PANE_FROZEN = 0x01; 72 const sal_uInt8 BIFF12_PANE_FROZENNOSPLIT = 0x02; 73 74 const sal_uInt16 BIFF12_SHEETVIEW_WINPROTECTED = 0x0001; 75 const sal_uInt16 BIFF12_SHEETVIEW_SHOWFORMULAS = 0x0002; 76 const sal_uInt16 BIFF12_SHEETVIEW_SHOWGRID = 0x0004; 77 const sal_uInt16 BIFF12_SHEETVIEW_SHOWHEADINGS = 0x0008; 78 const sal_uInt16 BIFF12_SHEETVIEW_SHOWZEROS = 0x0010; 79 const sal_uInt16 BIFF12_SHEETVIEW_RIGHTTOLEFT = 0x0020; 80 const sal_uInt16 BIFF12_SHEETVIEW_SELECTED = 0x0040; 81 const sal_uInt16 BIFF12_SHEETVIEW_SHOWRULER = 0x0080; 82 const sal_uInt16 BIFF12_SHEETVIEW_SHOWOUTLINE = 0x0100; 83 const sal_uInt16 BIFF12_SHEETVIEW_DEFGRIDCOLOR = 0x0200; 84 const sal_uInt16 BIFF12_SHEETVIEW_SHOWWHITESPACE = 0x0400; 85 86 const sal_uInt16 BIFF12_CHARTSHEETVIEW_SELECTED = 0x0001; 87 const sal_uInt16 BIFF12_CHARTSHEETVIEW_ZOOMTOFIT = 0x0002; 88 89 const sal_uInt8 BIFF12_WBVIEW_HIDDEN = 0x01; 90 const sal_uInt8 BIFF12_WBVIEW_MINIMIZED = 0x02; 91 const sal_uInt8 BIFF12_WBVIEW_SHOWHORSCROLL = 0x08; 92 const sal_uInt8 BIFF12_WBVIEW_SHOWVERSCROLL = 0x10; 93 const sal_uInt8 BIFF12_WBVIEW_SHOWTABBAR = 0x20; 94 const sal_uInt8 BIFF12_WBVIEW_AUTOFILTERGROUP = 0x40; 95 96 const sal_uInt8 BIFF_PANE_BOTTOMRIGHT = 0; /// Bottom-right pane. 97 const sal_uInt8 BIFF_PANE_TOPRIGHT = 1; /// Right, or top-right pane. 98 const sal_uInt8 BIFF_PANE_BOTTOMLEFT = 2; /// Bottom, or bottom-left pane. 99 const sal_uInt8 BIFF_PANE_TOPLEFT = 3; /// Single, top, left, or top-left pane. 100 101 const sal_uInt16 BIFF_WINDOW1_HIDDEN = 0x0001; 102 const sal_uInt16 BIFF_WINDOW1_MINIMIZED = 0x0002; 103 const sal_uInt16 BIFF_WINDOW1_SHOWHORSCROLL = 0x0008; 104 const sal_uInt16 BIFF_WINDOW1_SHOWVERSCROLL = 0x0010; 105 const sal_uInt16 BIFF_WINDOW1_SHOWTABBAR = 0x0020; 106 107 const sal_uInt16 BIFF_WINDOW2_SHOWFORMULAS = 0x0001; 108 const sal_uInt16 BIFF_WINDOW2_SHOWGRID = 0x0002; 109 const sal_uInt16 BIFF_WINDOW2_SHOWHEADINGS = 0x0004; 110 const sal_uInt16 BIFF_WINDOW2_FROZEN = 0x0008; 111 const sal_uInt16 BIFF_WINDOW2_SHOWZEROS = 0x0010; 112 const sal_uInt16 BIFF_WINDOW2_DEFGRIDCOLOR = 0x0020; 113 const sal_uInt16 BIFF_WINDOW2_RIGHTTOLEFT = 0x0040; 114 const sal_uInt16 BIFF_WINDOW2_SHOWOUTLINE = 0x0080; 115 const sal_uInt16 BIFF_WINDOW2_FROZENNOSPLIT = 0x0100; 116 const sal_uInt16 BIFF_WINDOW2_SELECTED = 0x0200; 117 const sal_uInt16 BIFF_WINDOW2_DISPLAYED = 0x0400; 118 const sal_uInt16 BIFF_WINDOW2_PAGEBREAKMODE = 0x0800; 119 120 // Attention: view settings in Calc do not use com.sun.star.view.DocumentZoomType! 121 const sal_Int16 API_ZOOMTYPE_PERCENT = 0; /// Zoom value in percent. 122 123 const sal_Int32 API_ZOOMVALUE_MIN = 20; /// Minimum zoom in Calc. 124 const sal_Int32 API_ZOOMVALUE_MAX = 400; /// Maximum zoom in Calc. 125 126 // no predefined constants for split mode 127 const sal_Int16 API_SPLITMODE_NONE = 0; /// No splits in window. 128 const sal_Int16 API_SPLITMODE_SPLIT = 1; /// Window is split. 129 const sal_Int16 API_SPLITMODE_FREEZE = 2; /// Window has frozen panes. 130 131 // no predefined constants for pane idetifiers 132 const sal_Int16 API_SPLITPANE_TOPLEFT = 0; /// Top-left, or top pane. 133 const sal_Int16 API_SPLITPANE_TOPRIGHT = 1; /// Top-right pane. 134 const sal_Int16 API_SPLITPANE_BOTTOMLEFT = 2; /// Bottom-left, bottom, left, or single pane. 135 const sal_Int16 API_SPLITPANE_BOTTOMRIGHT = 3; /// Bottom-right, or right pane. 136 137 // ---------------------------------------------------------------------------- 138 139 /** Returns the OOXML pane identifier from the passed BIFF pane id. */ 140 sal_Int32 lclGetOoxPaneId( sal_Int32 nBiffPaneId, sal_Int32 nDefaultPaneId ) 141 { 142 static const sal_Int32 spnPaneIds[] = { XML_bottomRight, XML_topRight, XML_bottomLeft, XML_topLeft }; 143 return STATIC_ARRAY_SELECT( spnPaneIds, nBiffPaneId, nDefaultPaneId ); 144 } 145 146 } // namespace 147 148 // ============================================================================ 149 150 PaneSelectionModel::PaneSelectionModel() : 151 mnActiveCellId( 0 ) 152 { 153 } 154 155 // ---------------------------------------------------------------------------- 156 157 SheetViewModel::SheetViewModel() : 158 mnWorkbookViewId( 0 ), 159 mnViewType( XML_normal ), 160 mnActivePaneId( XML_topLeft ), 161 mnPaneState( XML_split ), 162 mfSplitX( 0.0 ), 163 mfSplitY( 0.0 ), 164 mnCurrentZoom( 0 ), 165 mnNormalZoom( 0 ), 166 mnSheetLayoutZoom( 0 ), 167 mnPageLayoutZoom( 0 ), 168 mbSelected( false ), 169 mbRightToLeft( false ), 170 mbDefGridColor( true ), 171 mbShowFormulas( false ), 172 mbShowGrid( true ), 173 mbShowHeadings( true ), 174 mbShowZeros( true ), 175 mbShowOutline( true ), 176 mbZoomToFit( false ) 177 { 178 maGridColor.setIndexed( OOX_COLOR_WINDOWTEXT ); 179 } 180 181 bool SheetViewModel::isPageBreakPreview() const 182 { 183 return mnViewType == XML_pageBreakPreview; 184 } 185 186 sal_Int32 SheetViewModel::getNormalZoom() const 187 { 188 const sal_Int32& rnZoom = isPageBreakPreview() ? mnNormalZoom : mnCurrentZoom; 189 sal_Int32 nZoom = (rnZoom > 0) ? rnZoom : OOX_SHEETVIEW_NORMALZOOM_DEF; 190 return getLimitedValue< sal_Int32 >( nZoom, API_ZOOMVALUE_MIN, API_ZOOMVALUE_MAX ); 191 } 192 193 sal_Int32 SheetViewModel::getPageBreakZoom() const 194 { 195 const sal_Int32& rnZoom = isPageBreakPreview() ? mnCurrentZoom : mnSheetLayoutZoom; 196 sal_Int32 nZoom = (rnZoom > 0) ? rnZoom : OOX_SHEETVIEW_SHEETLAYZOOM_DEF; 197 return getLimitedValue< sal_Int32 >( nZoom, API_ZOOMVALUE_MIN, API_ZOOMVALUE_MAX ); 198 } 199 200 sal_Int32 SheetViewModel::getGridColor( const FilterBase& rFilter ) const 201 { 202 return mbDefGridColor ? API_RGB_TRANSPARENT : maGridColor.getColor( rFilter.getGraphicHelper() ); 203 } 204 205 const PaneSelectionModel* SheetViewModel::getPaneSelection( sal_Int32 nPaneId ) const 206 { 207 return maPaneSelMap.get( nPaneId ).get(); 208 } 209 210 const PaneSelectionModel* SheetViewModel::getActiveSelection() const 211 { 212 return getPaneSelection( mnActivePaneId ); 213 } 214 215 PaneSelectionModel& SheetViewModel::createPaneSelection( sal_Int32 nPaneId ) 216 { 217 PaneSelectionModelMap::mapped_type& rxPaneSel = maPaneSelMap[ nPaneId ]; 218 if( !rxPaneSel ) 219 rxPaneSel.reset( new PaneSelectionModel ); 220 return *rxPaneSel; 221 } 222 223 // ---------------------------------------------------------------------------- 224 225 SheetViewSettings::SheetViewSettings( const WorksheetHelper& rHelper ) : 226 WorksheetHelper( rHelper ) 227 { 228 } 229 230 void SheetViewSettings::importSheetView( const AttributeList& rAttribs ) 231 { 232 SheetViewModel& rModel = *createSheetView(); 233 rModel.maGridColor.setIndexed( rAttribs.getInteger( XML_colorId, OOX_COLOR_WINDOWTEXT ) ); 234 rModel.maFirstPos = getAddressConverter().createValidCellAddress( rAttribs.getString( XML_topLeftCell, OUString() ), getSheetIndex(), false ); 235 rModel.mnWorkbookViewId = rAttribs.getToken( XML_workbookViewId, 0 ); 236 rModel.mnViewType = rAttribs.getToken( XML_view, XML_normal ); 237 rModel.mnCurrentZoom = rAttribs.getInteger( XML_zoomScale, 100 ); 238 rModel.mnNormalZoom = rAttribs.getInteger( XML_zoomScaleNormal, 0 ); 239 rModel.mnSheetLayoutZoom = rAttribs.getInteger( XML_zoomScaleSheetLayoutView, 0 ); 240 rModel.mnPageLayoutZoom = rAttribs.getInteger( XML_zoomScalePageLayoutView, 0 ); 241 rModel.mbSelected = rAttribs.getBool( XML_tabSelected, false ); 242 rModel.mbRightToLeft = rAttribs.getBool( XML_rightToLeft, false ); 243 rModel.mbDefGridColor = rAttribs.getBool( XML_defaultGridColor, true ); 244 rModel.mbShowFormulas = rAttribs.getBool( XML_showFormulas, false ); 245 rModel.mbShowGrid = rAttribs.getBool( XML_showGridLines, true ); 246 rModel.mbShowHeadings = rAttribs.getBool( XML_showRowColHeaders, true ); 247 rModel.mbShowZeros = rAttribs.getBool( XML_showZeros, true ); 248 rModel.mbShowOutline = rAttribs.getBool( XML_showOutlineSymbols, true ); 249 } 250 251 void SheetViewSettings::importPane( const AttributeList& rAttribs ) 252 { 253 OSL_ENSURE( !maSheetViews.empty(), "SheetViewSettings::importPane - missing sheet view model" ); 254 if( !maSheetViews.empty() ) 255 { 256 SheetViewModel& rModel = *maSheetViews.back(); 257 rModel.maSecondPos = getAddressConverter().createValidCellAddress( rAttribs.getString( XML_topLeftCell, OUString() ), getSheetIndex(), false ); 258 rModel.mnActivePaneId = rAttribs.getToken( XML_activePane, XML_topLeft ); 259 rModel.mnPaneState = rAttribs.getToken( XML_state, XML_split ); 260 rModel.mfSplitX = rAttribs.getDouble( XML_xSplit, 0.0 ); 261 rModel.mfSplitY = rAttribs.getDouble( XML_ySplit, 0.0 ); 262 } 263 } 264 265 void SheetViewSettings::importSelection( const AttributeList& rAttribs ) 266 { 267 OSL_ENSURE( !maSheetViews.empty(), "SheetViewSettings::importSelection - missing sheet view model" ); 268 if( !maSheetViews.empty() ) 269 { 270 // pane this selection belongs to 271 sal_Int32 nPaneId = rAttribs.getToken( XML_pane, XML_topLeft ); 272 PaneSelectionModel& rSelData = maSheetViews.back()->createPaneSelection( nPaneId ); 273 // cursor position 274 rSelData.maActiveCell = getAddressConverter().createValidCellAddress( rAttribs.getString( XML_activeCell, OUString() ), getSheetIndex(), false ); 275 rSelData.mnActiveCellId = rAttribs.getInteger( XML_activeCellId, 0 ); 276 // selection 277 rSelData.maSelection.clear(); 278 getAddressConverter().convertToCellRangeList( rSelData.maSelection, rAttribs.getString( XML_sqref, OUString() ), getSheetIndex(), false ); 279 } 280 } 281 282 void SheetViewSettings::importChartSheetView( const AttributeList& rAttribs ) 283 { 284 SheetViewModel& rModel = *createSheetView(); 285 rModel.mnWorkbookViewId = rAttribs.getToken( XML_workbookViewId, 0 ); 286 rModel.mnCurrentZoom = rAttribs.getInteger( XML_zoomScale, 100 ); 287 rModel.mbSelected = rAttribs.getBool( XML_tabSelected, false ); 288 rModel.mbZoomToFit = rAttribs.getBool( XML_zoomToFit, false ); 289 } 290 291 void SheetViewSettings::importSheetView( SequenceInputStream& rStrm ) 292 { 293 SheetViewModel& rModel = *createSheetView(); 294 sal_uInt16 nFlags; 295 sal_Int32 nViewType; 296 BinAddress aFirstPos; 297 rStrm >> nFlags >> nViewType >> aFirstPos; 298 rModel.maGridColor.importColorId( rStrm ); 299 rModel.mnCurrentZoom = rStrm.readuInt16(); 300 rModel.mnNormalZoom = rStrm.readuInt16(); 301 rModel.mnSheetLayoutZoom = rStrm.readuInt16(); 302 rModel.mnPageLayoutZoom = rStrm.readuInt16(); 303 rStrm >> rModel.mnWorkbookViewId; 304 305 rModel.maFirstPos = getAddressConverter().createValidCellAddress( aFirstPos, getSheetIndex(), false ); 306 static const sal_Int32 spnViewTypes[] = { XML_normal, XML_pageBreakPreview, XML_pageLayout }; 307 rModel.mnViewType = STATIC_ARRAY_SELECT( spnViewTypes, nViewType, XML_normal ); 308 rModel.mbSelected = getFlag( nFlags, BIFF12_SHEETVIEW_SELECTED ); 309 rModel.mbRightToLeft = getFlag( nFlags, BIFF12_SHEETVIEW_RIGHTTOLEFT ); 310 rModel.mbDefGridColor = getFlag( nFlags, BIFF12_SHEETVIEW_DEFGRIDCOLOR ); 311 rModel.mbShowFormulas = getFlag( nFlags, BIFF12_SHEETVIEW_SHOWFORMULAS ); 312 rModel.mbShowGrid = getFlag( nFlags, BIFF12_SHEETVIEW_SHOWGRID ); 313 rModel.mbShowHeadings = getFlag( nFlags, BIFF12_SHEETVIEW_SHOWHEADINGS ); 314 rModel.mbShowZeros = getFlag( nFlags, BIFF12_SHEETVIEW_SHOWZEROS ); 315 rModel.mbShowOutline = getFlag( nFlags, BIFF12_SHEETVIEW_SHOWOUTLINE ); 316 } 317 318 void SheetViewSettings::importPane( SequenceInputStream& rStrm ) 319 { 320 OSL_ENSURE( !maSheetViews.empty(), "SheetViewSettings::importPane - missing sheet view model" ); 321 if( !maSheetViews.empty() ) 322 { 323 SheetViewModel& rModel = *maSheetViews.back(); 324 325 BinAddress aSecondPos; 326 sal_Int32 nActivePaneId; 327 sal_uInt8 nFlags; 328 rStrm >> rModel.mfSplitX >> rModel.mfSplitY >> aSecondPos >> nActivePaneId >> nFlags; 329 330 rModel.maSecondPos = getAddressConverter().createValidCellAddress( aSecondPos, getSheetIndex(), false ); 331 rModel.mnActivePaneId = lclGetOoxPaneId( nActivePaneId, XML_topLeft ); 332 rModel.mnPaneState = getFlagValue( nFlags, BIFF12_PANE_FROZEN, getFlagValue( nFlags, BIFF12_PANE_FROZENNOSPLIT, XML_frozen, XML_frozenSplit ), XML_split ); 333 } 334 } 335 336 void SheetViewSettings::importSelection( SequenceInputStream& rStrm ) 337 { 338 OSL_ENSURE( !maSheetViews.empty(), "SheetViewSettings::importSelection - missing sheet view model" ); 339 if( !maSheetViews.empty() ) 340 { 341 // pane this selection belongs to 342 sal_Int32 nPaneId = rStrm.readInt32(); 343 PaneSelectionModel& rPaneSel = maSheetViews.back()->createPaneSelection( lclGetOoxPaneId( nPaneId, -1 ) ); 344 // cursor position 345 BinAddress aActiveCell; 346 rStrm >> aActiveCell >> rPaneSel.mnActiveCellId; 347 rPaneSel.maActiveCell = getAddressConverter().createValidCellAddress( aActiveCell, getSheetIndex(), false ); 348 // selection 349 BinRangeList aSelection; 350 rStrm >> aSelection; 351 rPaneSel.maSelection.clear(); 352 getAddressConverter().convertToCellRangeList( rPaneSel.maSelection, aSelection, getSheetIndex(), false ); 353 } 354 } 355 356 void SheetViewSettings::importChartSheetView( SequenceInputStream& rStrm ) 357 { 358 SheetViewModel& rModel = *createSheetView(); 359 sal_uInt16 nFlags; 360 rStrm >> nFlags >> rModel.mnCurrentZoom >> rModel.mnWorkbookViewId; 361 362 rModel.mbSelected = getFlag( nFlags, BIFF12_CHARTSHEETVIEW_SELECTED ); 363 rModel.mbZoomToFit = getFlag( nFlags, BIFF12_CHARTSHEETVIEW_ZOOMTOFIT ); 364 } 365 366 void SheetViewSettings::importWindow2( BiffInputStream& rStrm ) 367 { 368 OSL_ENSURE( maSheetViews.empty(), "SheetViewSettings::importWindow2 - multiple WINDOW2 records" ); 369 SheetViewModel& rModel = *createSheetView(); 370 if( getBiff() == BIFF2 ) 371 { 372 rModel.mbShowFormulas = rStrm.readuInt8() != 0; 373 rModel.mbShowGrid = rStrm.readuInt8() != 0; 374 rModel.mbShowHeadings = rStrm.readuInt8() != 0; 375 rModel.mnPaneState = (rStrm.readuInt8() == 0) ? XML_split : XML_frozen; 376 rModel.mbShowZeros = rStrm.readuInt8() != 0; 377 BinAddress aFirstPos; 378 rStrm >> aFirstPos; 379 rModel.maFirstPos = getAddressConverter().createValidCellAddress( aFirstPos, getSheetIndex(), false ); 380 rModel.mbDefGridColor = rStrm.readuInt8() != 0; 381 rModel.maGridColor.importColorRgb( rStrm ); 382 } 383 else 384 { 385 sal_uInt16 nFlags; 386 BinAddress aFirstPos; 387 rStrm >> nFlags >> aFirstPos; 388 389 rModel.maFirstPos = getAddressConverter().createValidCellAddress( aFirstPos, getSheetIndex(), false ); 390 rModel.mnPaneState = getFlagValue( nFlags, BIFF_WINDOW2_FROZEN, getFlagValue( nFlags, BIFF_WINDOW2_FROZENNOSPLIT, XML_frozen, XML_frozenSplit ), XML_split ); 391 rModel.mbSelected = getFlag( nFlags, BIFF_WINDOW2_SELECTED ); 392 rModel.mbRightToLeft = getFlag( nFlags, BIFF_WINDOW2_RIGHTTOLEFT ); 393 rModel.mbDefGridColor = getFlag( nFlags, BIFF_WINDOW2_DEFGRIDCOLOR ); 394 rModel.mbShowFormulas = getFlag( nFlags, BIFF_WINDOW2_SHOWFORMULAS ); 395 rModel.mbShowGrid = getFlag( nFlags, BIFF_WINDOW2_SHOWGRID ); 396 rModel.mbShowHeadings = getFlag( nFlags, BIFF_WINDOW2_SHOWHEADINGS ); 397 rModel.mbShowZeros = getFlag( nFlags, BIFF_WINDOW2_SHOWZEROS ); 398 rModel.mbShowOutline = getFlag( nFlags, BIFF_WINDOW2_SHOWOUTLINE ); 399 400 if( getBiff() == BIFF8 ) 401 { 402 rModel.mnViewType = getFlagValue( nFlags, BIFF_WINDOW2_PAGEBREAKMODE, XML_pageBreakPreview, XML_normal ); 403 404 rModel.maGridColor.importColorId( rStrm ); 405 // zoom data not included in chart sheets 406 if( (getSheetType() != SHEETTYPE_CHARTSHEET) && (rStrm.getRemaining() >= 6) ) 407 { 408 rStrm.skip( 2 ); 409 sal_uInt16 nPageZoom, nNormalZoom; 410 rStrm >> nPageZoom >> nNormalZoom; 411 rModel.mnSheetLayoutZoom = nPageZoom; 412 rModel.mnNormalZoom = nNormalZoom; 413 } 414 } 415 else 416 { 417 rModel.maGridColor.importColorRgb( rStrm ); 418 } 419 } 420 } 421 422 void SheetViewSettings::importPane( BiffInputStream& rStrm ) 423 { 424 OSL_ENSURE( !maSheetViews.empty(), "SheetViewSettings::importPane - missing leading WINDOW2 record" ); 425 if( !maSheetViews.empty() ) 426 { 427 sal_uInt8 nActivePaneId; 428 sal_uInt16 nSplitX, nSplitY; 429 BinAddress aSecondPos; 430 rStrm >> nSplitX >> nSplitY >> aSecondPos >> nActivePaneId; 431 432 SheetViewModel& rModel = *maSheetViews.back(); 433 rModel.mfSplitX = nSplitX; 434 rModel.mfSplitY = nSplitY; 435 rModel.maSecondPos = getAddressConverter().createValidCellAddress( aSecondPos, getSheetIndex(), false ); 436 rModel.mnActivePaneId = lclGetOoxPaneId( nActivePaneId, XML_topLeft ); 437 } 438 } 439 440 void SheetViewSettings::importScl( BiffInputStream& rStrm ) 441 { 442 OSL_ENSURE( !maSheetViews.empty(), "SheetViewSettings::importScl - missing leading WINDOW2 record" ); 443 if( !maSheetViews.empty() ) 444 { 445 sal_uInt16 nNum, nDenom; 446 rStrm >> nNum >> nDenom; 447 OSL_ENSURE( nDenom > 0, "SheetViewSettings::importScl - invalid denominator" ); 448 if( nDenom > 0 ) 449 maSheetViews.back()->mnCurrentZoom = getLimitedValue< sal_Int32, sal_uInt16 >( (nNum * 100) / nDenom, 10, 400 ); 450 } 451 } 452 453 void SheetViewSettings::importSelection( BiffInputStream& rStrm ) 454 { 455 OSL_ENSURE( !maSheetViews.empty(), "SheetViewSettings::importPane - missing leading WINDOW2 record" ); 456 if( !maSheetViews.empty() ) 457 { 458 // pane this selection belongs to 459 sal_uInt8 nPaneId = rStrm.readuInt8(); 460 PaneSelectionModel& rPaneSel = maSheetViews.back()->createPaneSelection( lclGetOoxPaneId( nPaneId, -1 ) ); 461 // cursor position 462 BinAddress aActiveCell; 463 sal_uInt16 nActiveCellId; 464 rStrm >> aActiveCell >> nActiveCellId; 465 rPaneSel.maActiveCell = getAddressConverter().createValidCellAddress( aActiveCell, getSheetIndex(), false ); 466 rPaneSel.mnActiveCellId = nActiveCellId; 467 // selection 468 rPaneSel.maSelection.clear(); 469 BinRangeList aSelection; 470 aSelection.read( rStrm, false ); 471 getAddressConverter().convertToCellRangeList( rPaneSel.maSelection, aSelection, getSheetIndex(), false ); 472 } 473 } 474 475 void SheetViewSettings::finalizeImport() 476 { 477 // force creation of sheet view model to get the Excel defaults 478 SheetViewModelRef xModel = maSheetViews.empty() ? createSheetView() : maSheetViews.front(); 479 480 // #i59590# #158194# special handling for chart sheets (Excel ignores some settings in chart sheets) 481 if( getSheetType() == SHEETTYPE_CHARTSHEET ) 482 { 483 xModel->maPaneSelMap.clear(); 484 xModel->maFirstPos = xModel->maSecondPos = CellAddress( getSheetIndex(), 0, 0 ); 485 xModel->mnViewType = XML_normal; 486 xModel->mnActivePaneId = XML_topLeft; 487 xModel->mnPaneState = XML_split; 488 xModel->mfSplitX = xModel->mfSplitY = 0.0; 489 xModel->mbRightToLeft = false; 490 xModel->mbDefGridColor = true; 491 xModel->mbShowFormulas = false; 492 xModel->mbShowGrid = true; 493 xModel->mbShowHeadings = true; 494 xModel->mbShowZeros = true; 495 xModel->mbShowOutline = true; 496 } 497 498 // sheet selected (active sheet must be selected) 499 bool bSelected = xModel->mbSelected || (getSheetIndex() == getViewSettings().getActiveCalcSheet()); 500 501 // visible area and current cursor position (selection not supported via API) 502 CellAddress aFirstPos = xModel->maFirstPos; 503 const PaneSelectionModel* pPaneSel = xModel->getActiveSelection(); 504 CellAddress aCursor = pPaneSel ? pPaneSel->maActiveCell : aFirstPos; 505 506 // freeze/split position default 507 sal_Int16 nHSplitMode = API_SPLITMODE_NONE; 508 sal_Int16 nVSplitMode = API_SPLITMODE_NONE; 509 sal_Int32 nHSplitPos = 0; 510 sal_Int32 nVSplitPos = 0; 511 // active pane default 512 sal_Int16 nActivePane = API_SPLITPANE_BOTTOMLEFT; 513 514 // freeze/split position 515 if( (xModel->mnPaneState == XML_frozen) || (xModel->mnPaneState == XML_frozenSplit) ) 516 { 517 /* Frozen panes: handle split position as row/column positions. 518 #i35812# Excel uses number of visible rows/columns in the 519 frozen area (rows/columns scolled outside are not incuded), 520 Calc uses absolute position of first unfrozen row/column. */ 521 const CellAddress& rMaxApiPos = getAddressConverter().getMaxApiAddress(); 522 if( (xModel->mfSplitX >= 1.0) && (xModel->maFirstPos.Column + xModel->mfSplitX <= rMaxApiPos.Column) ) 523 nHSplitPos = static_cast< sal_Int32 >( xModel->maFirstPos.Column + xModel->mfSplitX ); 524 nHSplitMode = (nHSplitPos > 0) ? API_SPLITMODE_FREEZE : API_SPLITMODE_NONE; 525 if( (xModel->mfSplitY >= 1.0) && (xModel->maFirstPos.Row + xModel->mfSplitY <= rMaxApiPos.Row) ) 526 nVSplitPos = static_cast< sal_Int32 >( xModel->maFirstPos.Row + xModel->mfSplitY ); 527 nVSplitMode = (nVSplitPos > 0) ? API_SPLITMODE_FREEZE : API_SPLITMODE_NONE; 528 } 529 else if( xModel->mnPaneState == XML_split ) 530 { 531 // split window: view settings API uses twips... 532 nHSplitPos = getLimitedValue< sal_Int32, double >( xModel->mfSplitX + 0.5, 0, SAL_MAX_INT32 ); 533 nHSplitMode = (nHSplitPos > 0) ? API_SPLITMODE_SPLIT : API_SPLITMODE_NONE; 534 nVSplitPos = getLimitedValue< sal_Int32, double >( xModel->mfSplitY + 0.5, 0, SAL_MAX_INT32 ); 535 nVSplitMode = (nVSplitPos > 0) ? API_SPLITMODE_SPLIT : API_SPLITMODE_NONE; 536 } 537 538 // active pane 539 switch( xModel->mnActivePaneId ) 540 { 541 // no horizontal split -> always use left panes 542 // no vertical split -> always use *bottom* panes 543 case XML_topLeft: 544 nActivePane = (nVSplitMode == API_SPLITMODE_NONE) ? API_SPLITPANE_BOTTOMLEFT : API_SPLITPANE_TOPLEFT; 545 break; 546 case XML_topRight: 547 nActivePane = (nHSplitMode == API_SPLITMODE_NONE) ? 548 ((nVSplitMode == API_SPLITMODE_NONE) ? API_SPLITPANE_BOTTOMLEFT : API_SPLITPANE_TOPLEFT) : 549 ((nVSplitMode == API_SPLITMODE_NONE) ? API_SPLITPANE_BOTTOMRIGHT : API_SPLITPANE_TOPRIGHT); 550 break; 551 case XML_bottomLeft: 552 nActivePane = API_SPLITPANE_BOTTOMLEFT; 553 break; 554 case XML_bottomRight: 555 nActivePane = (nHSplitMode == API_SPLITMODE_NONE) ? API_SPLITPANE_BOTTOMLEFT : API_SPLITPANE_BOTTOMRIGHT; 556 break; 557 } 558 559 // write the sheet view settings into the property sequence 560 PropertyMap aPropMap; 561 aPropMap[ PROP_TableSelected ] <<= bSelected; 562 aPropMap[ PROP_CursorPositionX ] <<= aCursor.Column; 563 aPropMap[ PROP_CursorPositionY ] <<= aCursor.Row; 564 aPropMap[ PROP_HorizontalSplitMode ] <<= nHSplitMode; 565 aPropMap[ PROP_VerticalSplitMode ] <<= nVSplitMode; 566 aPropMap[ PROP_HorizontalSplitPositionTwips ] <<= nHSplitPos; 567 aPropMap[ PROP_VerticalSplitPositionTwips ] <<= nVSplitPos; 568 aPropMap[ PROP_ActiveSplitRange ] <<= nActivePane; 569 aPropMap[ PROP_PositionLeft ] <<= aFirstPos.Column; 570 aPropMap[ PROP_PositionTop ] <<= aFirstPos.Row; 571 aPropMap[ PROP_PositionRight ] <<= xModel->maSecondPos.Column; 572 aPropMap[ PROP_PositionBottom ] <<= ((nVSplitPos > 0) ? xModel->maSecondPos.Row : xModel->maFirstPos.Row); 573 aPropMap[ PROP_ZoomType ] <<= API_ZOOMTYPE_PERCENT; 574 aPropMap[ PROP_ZoomValue ] <<= static_cast< sal_Int16 >( xModel->getNormalZoom() ); 575 aPropMap[ PROP_PageViewZoomValue ] <<= static_cast< sal_Int16 >( xModel->getPageBreakZoom() ); 576 aPropMap[ PROP_GridColor ] <<= xModel->getGridColor( getBaseFilter() ); 577 aPropMap[ PROP_ShowPageBreakPreview ] <<= xModel->isPageBreakPreview(); 578 aPropMap[ PROP_ShowFormulas ] <<= xModel->mbShowFormulas; 579 aPropMap[ PROP_ShowGrid ] <<= xModel->mbShowGrid; 580 aPropMap[ PROP_HasColumnRowHeaders ] <<= xModel->mbShowHeadings; 581 aPropMap[ PROP_ShowZeroValues ] <<= xModel->mbShowZeros; 582 aPropMap[ PROP_IsOutlineSymbolsSet ] <<= xModel->mbShowOutline; 583 584 // store sheet view settings in global view settings object 585 getViewSettings().setSheetViewSettings( getSheetIndex(), xModel, Any( aPropMap.makePropertyValueSequence() ) ); 586 } 587 588 bool SheetViewSettings::isSheetRightToLeft() const 589 { 590 return !maSheetViews.empty() && maSheetViews.front()->mbRightToLeft; 591 } 592 593 // private -------------------------------------------------------------------- 594 595 SheetViewModelRef SheetViewSettings::createSheetView() 596 { 597 SheetViewModelRef xModel( new SheetViewModel ); 598 maSheetViews.push_back( xModel ); 599 return xModel; 600 } 601 602 // ============================================================================ 603 604 WorkbookViewModel::WorkbookViewModel() : 605 mnWinX( 0 ), 606 mnWinY( 0 ), 607 mnWinWidth( 0 ), 608 mnWinHeight( 0 ), 609 mnActiveSheet( 0 ), 610 mnFirstVisSheet( 0 ), 611 mnTabBarWidth( OOX_BOOKVIEW_TABBARRATIO_DEF ), 612 mnVisibility( XML_visible ), 613 mbShowTabBar( true ), 614 mbShowHorScroll( true ), 615 mbShowVerScroll( true ), 616 mbMinimized( false ) 617 { 618 } 619 620 // ---------------------------------------------------------------------------- 621 622 ViewSettings::ViewSettings( const WorkbookHelper& rHelper ) : 623 WorkbookHelper( rHelper ), 624 mbValidOleSize( false ) 625 { 626 } 627 628 void ViewSettings::importWorkbookView( const AttributeList& rAttribs ) 629 { 630 WorkbookViewModel& rModel = createWorkbookView(); 631 rModel.mnWinX = rAttribs.getInteger( XML_xWindow, 0 ); 632 rModel.mnWinY = rAttribs.getInteger( XML_yWindow, 0 ); 633 rModel.mnWinWidth = rAttribs.getInteger( XML_windowWidth, 0 ); 634 rModel.mnWinHeight = rAttribs.getInteger( XML_windowHeight, 0 ); 635 rModel.mnActiveSheet = rAttribs.getInteger( XML_activeTab, 0 ); 636 rModel.mnFirstVisSheet = rAttribs.getInteger( XML_firstSheet, 0 ); 637 rModel.mnTabBarWidth = rAttribs.getInteger( XML_tabRatio, 600 ); 638 rModel.mnVisibility = rAttribs.getToken( XML_visibility, XML_visible ); 639 rModel.mbShowTabBar = rAttribs.getBool( XML_showSheetTabs, true ); 640 rModel.mbShowHorScroll = rAttribs.getBool( XML_showHorizontalScroll, true ); 641 rModel.mbShowVerScroll = rAttribs.getBool( XML_showVerticalScroll, true ); 642 rModel.mbMinimized = rAttribs.getBool( XML_minimized, false ); 643 } 644 645 void ViewSettings::importOleSize( const AttributeList& rAttribs ) 646 { 647 OUString aRange = rAttribs.getString( XML_ref, OUString() ); 648 mbValidOleSize = getAddressConverter().convertToCellRange( maOleSize, aRange, 0, true, false ); 649 } 650 651 void ViewSettings::importWorkbookView( SequenceInputStream& rStrm ) 652 { 653 WorkbookViewModel& rModel = createWorkbookView(); 654 sal_uInt8 nFlags; 655 rStrm >> rModel.mnWinX >> rModel.mnWinY >> rModel.mnWinWidth >> rModel.mnWinHeight >> rModel.mnTabBarWidth >> rModel.mnFirstVisSheet >> rModel.mnActiveSheet >> nFlags; 656 rModel.mnVisibility = getFlagValue( nFlags, BIFF12_WBVIEW_HIDDEN, XML_hidden, XML_visible ); 657 rModel.mbShowTabBar = getFlag( nFlags, BIFF12_WBVIEW_SHOWTABBAR ); 658 rModel.mbShowHorScroll = getFlag( nFlags, BIFF12_WBVIEW_SHOWHORSCROLL ); 659 rModel.mbShowVerScroll = getFlag( nFlags, BIFF12_WBVIEW_SHOWVERSCROLL ); 660 rModel.mbMinimized = getFlag( nFlags, BIFF12_WBVIEW_MINIMIZED ); 661 } 662 663 void ViewSettings::importOleSize( SequenceInputStream& rStrm ) 664 { 665 BinRange aBinRange; 666 rStrm >> aBinRange; 667 mbValidOleSize = getAddressConverter().convertToCellRange( maOleSize, aBinRange, 0, true, false ); 668 } 669 670 void ViewSettings::importWindow1( BiffInputStream& rStrm ) 671 { 672 sal_uInt16 nWinX, nWinY, nWinWidth, nWinHeight; 673 rStrm >> nWinX >> nWinY >> nWinWidth >> nWinHeight; 674 675 // WINDOW1 record occures in every sheet in BIFF4W 676 OSL_ENSURE( maBookViews.empty() || ((getBiff() == BIFF4) && isWorkbookFile()), 677 "ViewSettings::importWindow1 - multiple WINDOW1 records" ); 678 WorkbookViewModel& rModel = createWorkbookView(); 679 rModel.mnWinX = nWinX; 680 rModel.mnWinY = nWinY; 681 rModel.mnWinWidth = nWinWidth; 682 rModel.mnWinHeight = nWinHeight; 683 684 if( getBiff() <= BIFF4 ) 685 { 686 sal_uInt8 nHidden; 687 rStrm >> nHidden; 688 rModel.mnVisibility = (nHidden == 0) ? XML_visible : XML_hidden; 689 } 690 else 691 { 692 sal_uInt16 nFlags, nActiveTab, nFirstVisTab, nSelectCnt, nTabBarWidth; 693 rStrm >> nFlags >> nActiveTab >> nFirstVisTab >> nSelectCnt >> nTabBarWidth; 694 695 rModel.mnActiveSheet = nActiveTab; 696 rModel.mnFirstVisSheet = nFirstVisTab; 697 rModel.mnTabBarWidth = nTabBarWidth; 698 rModel.mnVisibility = getFlagValue( nFlags, BIFF_WINDOW1_HIDDEN, XML_hidden, XML_visible ); 699 rModel.mbMinimized = getFlag( nFlags, BIFF_WINDOW1_MINIMIZED ); 700 rModel.mbShowHorScroll = getFlag( nFlags, BIFF_WINDOW1_SHOWHORSCROLL ); 701 rModel.mbShowVerScroll = getFlag( nFlags, BIFF_WINDOW1_SHOWVERSCROLL ); 702 rModel.mbShowTabBar = getFlag( nFlags, BIFF_WINDOW1_SHOWTABBAR ); 703 } 704 } 705 706 void ViewSettings::importOleSize( BiffInputStream& rStrm ) 707 { 708 rStrm.skip( 2 ); 709 BinRange aBinRange; 710 aBinRange.read( rStrm, false ); 711 mbValidOleSize = getAddressConverter().convertToCellRange( maOleSize, aBinRange, 0, true, false ); 712 } 713 714 void ViewSettings::setSheetViewSettings( sal_Int16 nSheet, const SheetViewModelRef& rxSheetView, const Any& rProperties ) 715 { 716 maSheetViews[ nSheet ] = rxSheetView; 717 maSheetProps[ nSheet ] = rProperties; 718 } 719 720 void ViewSettings::setSheetUsedArea( const CellRangeAddress& rUsedArea ) 721 { 722 maSheetUsedAreas[ rUsedArea.Sheet ] = rUsedArea; 723 } 724 725 void ViewSettings::finalizeImport() 726 { 727 const WorksheetBuffer& rWorksheets = getWorksheets(); 728 if( rWorksheets.getWorksheetCount() <= 0 ) return; 729 730 // force creation of workbook view model to get the Excel defaults 731 const WorkbookViewModel& rModel = maBookViews.empty() ? createWorkbookView() : *maBookViews.front(); 732 733 // show object mode is part of workbook settings 734 sal_Int16 nShowMode = getWorkbookSettings().getApiShowObjectMode(); 735 736 // view settings for all sheets 737 Reference< XNameContainer > xSheetsNC = ContainerHelper::createNameContainer( getBaseFilter().getComponentContext() ); 738 if( !xSheetsNC.is() ) return; 739 for( SheetPropertiesMap::const_iterator aIt = maSheetProps.begin(), aEnd = maSheetProps.end(); aIt != aEnd; ++aIt ) 740 ContainerHelper::insertByName( xSheetsNC, rWorksheets.getCalcSheetName( aIt->first ), aIt->second ); 741 742 // use active sheet to set sheet properties that are document-global in Calc 743 sal_Int16 nActiveSheet = getActiveCalcSheet(); 744 SheetViewModelRef& rxActiveSheetView = maSheetViews[ nActiveSheet ]; 745 OSL_ENSURE( rxActiveSheetView.get(), "ViewSettings::finalizeImport - missing active sheet view settings" ); 746 if( !rxActiveSheetView ) 747 rxActiveSheetView.reset( new SheetViewModel ); 748 749 Reference< XIndexContainer > xContainer = ContainerHelper::createIndexContainer( getBaseFilter().getComponentContext() ); 750 if( xContainer.is() ) try 751 { 752 PropertyMap aPropMap; 753 aPropMap[ PROP_Tables ] <<= xSheetsNC; 754 aPropMap[ PROP_ActiveTable ] <<= rWorksheets.getCalcSheetName( nActiveSheet ); 755 aPropMap[ PROP_HasHorizontalScrollBar ] <<= rModel.mbShowHorScroll; 756 aPropMap[ PROP_HasVerticalScrollBar ] <<= rModel.mbShowVerScroll; 757 aPropMap[ PROP_HasSheetTabs ] <<= rModel.mbShowTabBar; 758 aPropMap[ PROP_RelativeHorizontalTabbarWidth ] <<= double( rModel.mnTabBarWidth / 1000.0 ); 759 aPropMap[ PROP_ShowObjects ] <<= nShowMode; 760 aPropMap[ PROP_ShowCharts ] <<= nShowMode; 761 aPropMap[ PROP_ShowDrawing ] <<= nShowMode; 762 aPropMap[ PROP_GridColor ] <<= rxActiveSheetView->getGridColor( getBaseFilter() ); 763 aPropMap[ PROP_ShowPageBreakPreview ] <<= rxActiveSheetView->isPageBreakPreview(); 764 aPropMap[ PROP_ShowFormulas ] <<= rxActiveSheetView->mbShowFormulas; 765 aPropMap[ PROP_ShowGrid ] <<= rxActiveSheetView->mbShowGrid; 766 aPropMap[ PROP_HasColumnRowHeaders ] <<= rxActiveSheetView->mbShowHeadings; 767 aPropMap[ PROP_ShowZeroValues ] <<= rxActiveSheetView->mbShowZeros; 768 aPropMap[ PROP_IsOutlineSymbolsSet ] <<= rxActiveSheetView->mbShowOutline; 769 770 xContainer->insertByIndex( 0, Any( aPropMap.makePropertyValueSequence() ) ); 771 Reference< XIndexAccess > xIAccess( xContainer, UNO_QUERY_THROW ); 772 Reference< XViewDataSupplier > xViewDataSuppl( getDocument(), UNO_QUERY_THROW ); 773 xViewDataSuppl->setViewData( xIAccess ); 774 } 775 catch( Exception& ) 776 { 777 OSL_ENSURE( false, "ViewSettings::finalizeImport - cannot create document view settings" ); 778 } 779 780 /* Set visible area to be used if this document is an embedded OLE object. 781 #i44077# If a new OLE object is inserted from file, there is no OLESIZE 782 record in the Excel file. In this case, use the used area calculated 783 from file contents (used cells and drawing objects). */ 784 maOleSize.Sheet = nActiveSheet; 785 const CellRangeAddress* pVisibleArea = mbValidOleSize ? 786 &maOleSize : ContainerHelper::getMapElement( maSheetUsedAreas, nActiveSheet ); 787 if( pVisibleArea ) 788 { 789 // calculate the visible area in units of 1/100 mm 790 PropertySet aRangeProp( getCellRangeFromDoc( *pVisibleArea ) ); 791 Point aPos; 792 Size aSize; 793 if( aRangeProp.getProperty( aPos, PROP_Position ) && aRangeProp.getProperty( aSize, PROP_Size ) ) 794 { 795 // set the visible area as sequence of long at the media descriptor 796 Sequence< sal_Int32 > aWinExtent( 4 ); 797 aWinExtent[ 0 ] = aPos.X; 798 aWinExtent[ 1 ] = aPos.Y; 799 aWinExtent[ 2 ] = aPos.X + aSize.Width; 800 aWinExtent[ 3 ] = aPos.Y + aSize.Height; 801 getBaseFilter().getMediaDescriptor()[ CREATE_OUSTRING( "WinExtent" ) ] <<= aWinExtent; 802 } 803 } 804 } 805 806 sal_Int16 ViewSettings::getActiveCalcSheet() const 807 { 808 return maBookViews.empty() ? 0 : ::std::max< sal_Int16 >( getWorksheets().getCalcSheetIndex( maBookViews.front()->mnActiveSheet ), 0 ); 809 } 810 811 // private -------------------------------------------------------------------- 812 813 WorkbookViewModel& ViewSettings::createWorkbookView() 814 { 815 WorkbookViewModelRef xModel( new WorkbookViewModel ); 816 maBookViews.push_back( xModel ); 817 return *xModel; 818 } 819 820 // ============================================================================ 821 822 } // namespace xls 823 } // namespace oox 824