Updated core
[LibreOffice.git] / svtools / source / control / ruler.cxx
blob7fd44c7dd0c2833a59ee4f80eb8619a5183612b3
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <string.h>
21 #include <tools/debug.hxx>
22 #include <vcl/svapp.hxx>
23 #include <tools/poly.hxx>
24 #include <vcl/i18nhelp.hxx>
26 #include <svtools/ruler.hxx>
28 // =======================================================================
30 #define RULER_OFF 3
31 #define RULER_TEXTOFF 5
32 #define RULER_RESIZE_OFF 4
33 #define RULER_MIN_SIZE 3
35 #define RULER_TICK1_WIDTH 1
36 #define RULER_TICK2_WIDTH 3
38 #define RULER_VAR_SIZE 8
40 #define RULER_TAB_HEIGHT2 2
41 #define RULER_TAB_WIDTH2 2
42 #define RULER_TAB_CWIDTH 8
43 #define RULER_TAB_CWIDTH2 4
44 #define RULER_TAB_CWIDTH3 4
45 #define RULER_TAB_CWIDTH4 2
46 #define RULER_TAB_DHEIGHT 4
47 #define RULER_TAB_DHEIGHT2 1
48 #define RULER_TAB_DWIDTH 5
49 #define RULER_TAB_DWIDTH2 3
50 #define RULER_TAB_DWIDTH3 3
51 #define RULER_TAB_DWIDTH4 1
53 #define RULER_UPDATE_LINES 0x01
54 #define RULER_UPDATE_DRAW 0x02
56 #define RULER_CLIP 150
58 // =======================================================================
60 #define RULER_UNIT_MM 0
61 #define RULER_UNIT_CM 1
62 #define RULER_UNIT_M 2
63 #define RULER_UNIT_KM 3
64 #define RULER_UNIT_INCH 4
65 #define RULER_UNIT_FOOT 5
66 #define RULER_UNIT_MILE 6
67 #define RULER_UNIT_POINT 7
68 #define RULER_UNIT_PICA 8
69 #define RULER_UNIT_CHAR 9
70 #define RULER_UNIT_LINE 10
71 #define RULER_UNIT_COUNT 11
73 // -----------------
74 // - ImplRulerData -
75 // -----------------
76 class ImplRulerData
78 friend class Ruler;
80 private:
81 RulerLine* pLines;
82 RulerBorder* pBorders;
83 RulerIndent* pIndents;
84 RulerTab* pTabs;
85 long nNullVirOff;
86 long nRulVirOff;
87 long nRulWidth;
88 long nPageOff;
89 long nPageWidth;
90 long nNullOff;
91 long nMargin1;
92 long nMargin2;
93 sal_uInt16 nLines;
94 sal_uInt16 nBorders;
95 sal_uInt16 nIndents;
96 sal_uInt16 nTabs;
97 sal_uInt16 nMargin1Style;
98 sal_uInt16 nMargin2Style;
99 sal_Bool bAutoPageWidth;
100 sal_Bool bTextRTL;
102 public:
103 ImplRulerData();
104 ~ImplRulerData();
105 ImplRulerData& operator=( const ImplRulerData& rData );
109 struct ImplRulerUnitData
111 MapUnit eMapUnit; // MAP_UNIT zum Umrechnen
112 long nTickUnit; // Teiler fuer Einheit
113 long nTick1; // Schrittweite
114 long nTick2; // Tick fuer halbe Werte
115 long nTick3; // Tick fuer Zahlenausgabe
116 long n100THMM; // Teiler fuer Einheit
117 sal_uInt16 nUnitDigits; // Anzahl Nachkommastellen
118 sal_Char aUnitStr[8]; // Einheiten-String
121 static ImplRulerUnitData aImplRulerUnitTab[RULER_UNIT_COUNT] =
123 { MAP_100TH_MM, 100, 25, 50, 100, 100, 3, " mm" }, // MM
124 { MAP_100TH_MM, 1000, 250, 500, 1000, 1000, 3, " cm" }, // CM
125 { MAP_MM, 1000, 250, 500, 1000, 10000, 4, " m" }, // M
126 { MAP_CM, 100000, 25000, 50000, 100000, 100000, 6, " km" }, // KM
127 { MAP_1000TH_INCH, 1000, 125, 500, 1000, 25400, 3, "\"" }, // INCH
128 { MAP_100TH_INCH, 1200, 120, 600, 1200, 30480, 3, "'" }, // FOOT
129 { MAP_10TH_INCH, 633600, 63360, 316800, 633600, 1609344, 4, " miles" }, // MILE
130 { MAP_POINT, 1, 12, 12, 36, 353, 2, " pt" }, // POINT
131 { MAP_100TH_MM, 423, 423, 423, 846, 423, 3, " pi" }, // PICA
132 { MAP_100TH_MM, 371, 371, 371, 743, 371, 3, " ch" }, // CHAR
133 { MAP_100TH_MM, 551, 551, 551, 1102, 551, 3, " li" } // LINE
136 // =======================================================================
138 struct ImplRulerHitTest
140 long nPos;
141 RulerType eType;
142 sal_uInt16 nAryPos;
143 sal_uInt16 mnDragSize;
144 sal_Bool bSize;
145 sal_Bool bSizeBar;
146 sal_Bool bExpandTest;
147 ImplRulerHitTest() :
148 bExpandTest( sal_False ) {}
151 // =======================================================================
153 ImplRulerData::ImplRulerData()
155 memset( this, 0, sizeof( ImplRulerData ) );
157 // PageBreite == EditWinBreite
158 bAutoPageWidth = sal_True;
161 // -----------------------------------------------------------------------
163 ImplRulerData::~ImplRulerData()
165 delete[] pLines;
166 delete[] pBorders;
167 delete[] pIndents;
168 delete[] pTabs;
171 // -----------------------------------------------------------------------
173 ImplRulerData& ImplRulerData::operator=( const ImplRulerData& rData )
175 if( this == &rData )
176 return *this;
178 delete[] pLines;
179 delete[] pBorders;
180 delete[] pIndents;
181 delete[] pTabs;
183 memcpy( this, &rData, sizeof( ImplRulerData ) );
185 if ( rData.pLines )
187 pLines = new RulerLine[nLines];
188 memcpy( pLines, rData.pLines, nLines*sizeof( RulerLine ) );
191 if ( rData.pBorders )
193 pBorders = new RulerBorder[nBorders];
194 memcpy( pBorders, rData.pBorders, nBorders*sizeof( RulerBorder ) );
197 if ( rData.pIndents )
199 pIndents = new RulerIndent[nIndents];
200 memcpy( pIndents, rData.pIndents, nIndents*sizeof( RulerIndent ) );
203 if ( rData.pTabs )
205 pTabs = new RulerTab[nTabs];
206 memcpy( pTabs, rData.pTabs, nTabs*sizeof( RulerTab ) );
209 return *this;
212 // =======================================================================
214 void Ruler::ImplInit( WinBits nWinBits )
216 // Default WinBits setzen
217 if ( !(nWinBits & WB_VERT) )
219 nWinBits |= WB_HORZ;
221 // --- RTL --- no UI mirroring for horizontal rulers, because
222 // the document is also not mirrored
223 EnableRTL( sal_False );
226 // Variablen initialisieren
227 mnWinStyle = nWinBits; // Window-Style
228 mnBorderOff = 0; // Border-Offset
229 mnWinOff = 0; // EditWinOffset
230 mnWinWidth = 0; // EditWinWidth
231 mnWidth = 0; // Fensterbreite
232 mnHeight = 0; // Fensterhoehe
233 mnVirOff = 0; // Offset des VirtualDeice vom linke/oberen Rand
234 mnVirWidth = 0; // Breite bzw. Hoehe vom VirtualDevice
235 mnVirHeight = 0; // Hoehe bzw. Breite vom VirtualDevice
236 mnDragPos = 0; // Drag-Position (NullPunkt)
237 mnUpdateEvtId = 0; // Noch kein Update-Event verschickt
238 mnDragAryPos = 0; // Drag-Array-Index
239 mnDragSize = 0; // Wird beim Draggen die Groesse geaendert
240 mnDragScroll = 0; // Soll beim Draggen gescrollt werden
241 mnDragModifier = 0; // Modifier-Tasten beim Draggen
242 mnExtraStyle = 0; // Style des Extra-Feldes
243 mnExtraClicks = 0; // Click-Anzahl fuer Extra-Feld
244 mnExtraModifier = 0; // Modifier-Tasten beim Click im Extrafeld
245 mnCharWidth = 371;
246 mnLineHeight = 551;
247 mbCalc = sal_True; // Muessen Pagebreiten neu berechnet werden
248 mbFormat = sal_True; // Muss neu ausgegeben werden
249 mbDrag = sal_False; // Sind wir im Drag-Modus
250 mbDragDelete = sal_False; // Wird Maus beim Draggen unten rausgezogen
251 mbDragCanceled = sal_False; // Wurde Dragging abgebrochen
252 mbAutoWinWidth = sal_True; // EditWinBreite == RulerBreite
253 mbActive = sal_True; // Ist Lineal aktiv
254 mnUpdateFlags = 0; // Was soll im Update-Handler upgedatet werden
255 mpData = mpSaveData; // Wir zeigen auf die normalen Daten
256 meExtraType = RULER_EXTRA_DONTKNOW; // Was im ExtraFeld dargestellt wird
257 meDragType = RULER_TYPE_DONTKNOW; // Gibt an, was gedragt wird
259 // Units initialisieren
260 mnUnitIndex = RULER_UNIT_CM;
261 meUnit = FUNIT_CM;
262 maZoom = Fraction( 1, 1 );
263 meSourceUnit = MAP_100TH_MM;
265 // Border-Breiten berechnen
266 if ( nWinBits & WB_BORDER )
267 mnBorderWidth = 1;
268 else
269 mnBorderWidth = 0;
271 // Einstellungen setzen
272 ImplInitSettings( sal_True, sal_True, sal_True );
274 // Setup the default size
275 Rectangle aRect;
276 GetTextBoundRect( aRect, OUString( "0123456789" ) );
277 long nDefHeight = aRect.GetHeight() + RULER_OFF*2 + RULER_TEXTOFF*2 + mnBorderWidth;
279 Size aDefSize;
280 if ( nWinBits & WB_HORZ )
281 aDefSize.Height() = nDefHeight;
282 else
283 aDefSize.Width() = nDefHeight;
284 SetOutputSizePixel( aDefSize );
285 SetType(WINDOW_RULER);
288 // -----------------------------------------------------------------------
290 Ruler::Ruler( Window* pParent, WinBits nWinStyle ) :
291 Window( pParent, nWinStyle & WB_3DLOOK ),
292 maVirDev( *this ),
293 maMapMode( MAP_100TH_MM ),
294 mpSaveData(new ImplRulerData),
295 mpData(0),
296 mpDragData(new ImplRulerData)
298 ImplInit( nWinStyle );
301 // -----------------------------------------------------------------------
303 Ruler::~Ruler()
305 if ( mnUpdateEvtId )
306 Application::RemoveUserEvent( mnUpdateEvtId );
307 delete mpSaveData;
308 delete mpDragData;
311 // -----------------------------------------------------------------------
313 void Ruler::ImplVDrawLine( long nX1, long nY1, long nX2, long nY2 )
315 if ( nX1 < -RULER_CLIP )
317 nX1 = -RULER_CLIP;
318 if ( nX2 < -RULER_CLIP )
319 return;
321 long nClip = mnVirWidth+RULER_CLIP;
322 if ( nX2 > nClip )
324 nX2 = nClip;
325 if ( nX1 > nClip )
326 return;
329 if ( mnWinStyle & WB_HORZ )
330 maVirDev.DrawLine( Point( nX1, nY1 ), Point( nX2, nY2 ) );
331 else
332 maVirDev.DrawLine( Point( nY1, nX1 ), Point( nY2, nX2 ) );
335 // -----------------------------------------------------------------------
337 void Ruler::ImplVDrawRect( long nX1, long nY1, long nX2, long nY2 )
339 if ( nX1 < -RULER_CLIP )
341 nX1 = -RULER_CLIP;
342 if ( nX2 < -RULER_CLIP )
343 return;
345 long nClip = mnVirWidth+RULER_CLIP;
346 if ( nX2 > nClip )
348 nX2 = nClip;
349 if ( nX1 > nClip )
350 return;
353 if ( mnWinStyle & WB_HORZ )
354 maVirDev.DrawRect( Rectangle( nX1, nY1, nX2, nY2 ) );
355 else
356 maVirDev.DrawRect( Rectangle( nY1, nX1, nY2, nX2 ) );
359 // -----------------------------------------------------------------------
361 void Ruler::ImplVDrawText( long nX, long nY, const String& rText, long nMin, long nMax )
363 Rectangle aRect;
364 maVirDev.GetTextBoundRect( aRect, rText );
366 long nShiftX = ( aRect.GetWidth() / 2 ) + aRect.Left();
367 long nShiftY = ( aRect.GetHeight() / 2 ) + aRect.Top();
369 if ( (nX > -RULER_CLIP) && (nX < mnVirWidth+RULER_CLIP) && ( nX < nMax - nShiftX ) && ( nX > nMin + nShiftX ) )
371 if ( mnWinStyle & WB_HORZ )
372 maVirDev.DrawText( Point( nX - nShiftX, nY - nShiftY ), rText );
373 else
374 maVirDev.DrawText( Point( nY - nShiftX, nX - nShiftY ), rText );
378 // -----------------------------------------------------------------------
380 void Ruler::ImplInvertLines( sal_Bool bErase )
382 // Positionslinien
383 if ( mpData->nLines && mbActive && !mbDrag && !mbFormat &&
384 !(mnUpdateFlags & RULER_UPDATE_LINES) )
386 long n;
387 long nNullWinOff = mpData->nNullVirOff+mnVirOff;
388 long nRulX1 = mpData->nRulVirOff+mnVirOff;
389 long nRulX2 = nRulX1+mpData->nRulWidth;
390 long nY = (RULER_OFF*2)+mnVirHeight-1;
392 // Rectangle berechnen
393 Rectangle aRect;
394 if ( mnWinStyle & WB_HORZ )
395 aRect.Bottom() = nY;
396 else
397 aRect.Right() = nY;
399 // Linien ausgeben
400 for ( sal_uInt16 i = 0; i < mpData->nLines; i++ )
402 n = mpData->pLines[i].nPos+nNullWinOff;
403 if ( (n >= nRulX1) && (n < nRulX2) )
405 if ( mnWinStyle & WB_HORZ )
407 aRect.Left() = n;
408 aRect.Right() = n;
410 else
412 aRect.Top() = n;
413 aRect.Bottom() = n;
415 if ( bErase )
417 Rectangle aTempRect = aRect;
418 if ( mnWinStyle & WB_HORZ )
419 aTempRect.Bottom() = RULER_OFF-1;
420 else
421 aTempRect.Right() = RULER_OFF-1;
422 Erase( aTempRect );
423 if ( mnWinStyle & WB_HORZ )
425 aTempRect.Bottom() = aRect.Bottom();
426 aTempRect.Top() = aTempRect.Bottom()-RULER_OFF+1;
428 else
430 aTempRect.Right() = aRect.Right();
431 aTempRect.Left() = aTempRect.Right()-RULER_OFF+1;
433 Erase( aTempRect );
435 Invert( aRect );
441 // -----------------------------------------------------------------------
443 void Ruler::ImplDrawTicks( long nMin, long nMax, long nStart, long nCenter )
445 long n = 0;
446 long nTick3 = aImplRulerUnitTab[mnUnitIndex].nTick3;
447 long nTickCount = aImplRulerUnitTab[mnUnitIndex].nTick1;
448 Size aPixSize = maVirDev.LogicToPixel( Size( nTick3, nTick3 ), maMapMode );
449 long nTickWidth;
450 sal_Bool bNoTicks = sal_False;
452 long nTickUnit = 0;
453 long nTick2 = 0;
454 if ( mnUnitIndex == RULER_UNIT_CHAR )
456 if ( mnCharWidth == 0 )
457 mnCharWidth = 371;
458 nTick3 = mnCharWidth*2;
459 nTickCount = mnCharWidth;
460 nTickUnit = mnCharWidth;
461 nTick2 = mnCharWidth;
463 else if ( mnUnitIndex == RULER_UNIT_LINE )
465 if ( mnLineHeight == 0 )
466 mnLineHeight = 551;
467 nTick3 = mnLineHeight*2;
468 nTickCount = mnLineHeight;
469 nTickUnit = mnLineHeight;
470 nTick2 = mnLineHeight;
472 aPixSize = maVirDev.LogicToPixel( Size( nTick3, nTick3 ), maMapMode );
474 // Groessenvorberechnung
475 // Sizes calculation
476 if ( mnWinStyle & WB_HORZ )
477 nTickWidth = aPixSize.Width();
478 else
480 Font aFont = GetFont();
481 if ( mnWinStyle & WB_RIGHT_ALIGNED )
482 aFont.SetOrientation( 2700 );
483 else
484 aFont.SetOrientation( 900 );
485 maVirDev.SetFont( aFont );
486 nTickWidth = aPixSize.Height();
488 long nMaxWidth = maVirDev.PixelToLogic( Size( mpData->nPageWidth, 0 ), maMapMode ).Width();
489 if ( nMaxWidth < 0 )
490 nMaxWidth = -nMaxWidth;
492 if (( mnUnitIndex == RULER_UNIT_CHAR ) || ( mnUnitIndex == RULER_UNIT_LINE ))
493 nMaxWidth /= nTickUnit;
494 else
495 nMaxWidth /= aImplRulerUnitTab[mnUnitIndex].nTickUnit;
496 OUString aNumStr = OUString::number(nMaxWidth);
497 long nTxtWidth = GetTextWidth( aNumStr );
498 const long nTextOff = 4;
499 if ( nTickWidth < nTxtWidth+nTextOff )
501 // Calculate the scale of the ruler
502 long nMulti = 1;
503 long nOrgTick3 = nTick3;
504 while ( nTickWidth < nTxtWidth+nTextOff )
506 long nOldMulti = nMulti;
507 if ( !nTickWidth ) //If nTickWidth equals 0
508 nMulti *= 10;
509 else if ( nMulti < 10 )
510 nMulti++;
511 else if ( nMulti < 100 )
512 nMulti += 10;
513 else if ( nMulti < 1000 )
514 nMulti += 100;
515 else
516 nMulti += 1000;
517 // Ueberlauf, dann geben wir nichts aus, da wir bei so einem
518 // unsinnigen Massstab sowieso nichts vernuenftiges anzeigen
519 // koennen
520 if ( nMulti < nOldMulti )
522 bNoTicks = sal_True;
523 break;
526 nTick3 = nOrgTick3 * nMulti;
527 aPixSize = maVirDev.LogicToPixel( Size( nTick3, nTick3 ), maMapMode );
528 if ( mnWinStyle & WB_HORZ )
529 nTickWidth = aPixSize.Width();
530 else
531 nTickWidth = aPixSize.Height();
533 nTickCount = nTick3;
535 else
536 maVirDev.SetLineColor( GetSettings().GetStyleSettings().GetShadowColor() );
538 if ( !bNoTicks )
540 long nTick = 0;
541 while ( ((nStart-n) >= nMin) || ((nStart+n) <= nMax) )
543 // Null-Punkt
544 if ( !nTick )
546 if ( nStart > nMin )
548 // 0 is only painted when Margin1 is not equal to zero
549 if ( (mpData->nMargin1Style & RULER_STYLE_INVISIBLE) || (mpData->nMargin1 != 0) )
551 aNumStr = "0";
552 ImplVDrawText( nStart, nCenter, aNumStr );
556 else
558 aPixSize = maVirDev.LogicToPixel( Size( nTick, nTick ), maMapMode );
560 if ( mnWinStyle & WB_HORZ )
561 n = aPixSize.Width();
562 else
563 n = aPixSize.Height();
565 // Tick3 - Output (Text)
566 if ( !(nTick % nTick3) )
568 if ( ( mnUnitIndex == RULER_UNIT_CHAR ) || ( mnUnitIndex == RULER_UNIT_LINE ) )
569 aNumStr = OUString::valueOf( static_cast<sal_Int64>( nTick / nTickUnit ) );
570 else
571 aNumStr = OUString::valueOf( static_cast<sal_Int64>( nTick / aImplRulerUnitTab[mnUnitIndex].nTickUnit ) );
573 ImplVDrawText( nStart + n, nCenter, aNumStr, nMin, nMax );
574 ImplVDrawText( nStart - n, nCenter, aNumStr, nMin, nMax );
576 // Tick/Tick2 - Output (Strokes)
577 else
579 if ( ( mnUnitIndex != RULER_UNIT_CHAR ) && ( mnUnitIndex != RULER_UNIT_LINE ) )
580 nTick2 = aImplRulerUnitTab[mnUnitIndex].nTick2;
581 if ( !(nTick % nTick2 ) )
582 nTickWidth = RULER_TICK2_WIDTH;
583 else
584 nTickWidth = RULER_TICK1_WIDTH;
585 long nT1 = nCenter-(nTickWidth/2);
586 long nT2 = nT1+nTickWidth-1;
587 long nT;
589 nT = nStart+n;
590 if ( nT < nMax )
591 ImplVDrawLine( nT, nT1, nT, nT2 );
592 nT = nStart-n;
593 if ( nT > nMin )
594 ImplVDrawLine( nT, nT1, nT, nT2 );
597 // #i49017# with some zoom factors the value nTick can overflow
598 if( ((sal_uLong)nTick + (sal_uLong)nTickCount) > (sal_uLong)LONG_MAX)
599 break;
600 nTick += nTickCount;
605 // -----------------------------------------------------------------------
607 void Ruler::ImplDrawBorders( long nMin, long nMax, long nVirTop, long nVirBottom )
609 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
610 long n;
611 long n1;
612 long n2;
613 long nTemp1;
614 long nTemp2;
615 sal_uInt16 i;
617 for ( i = 0; i < mpData->nBorders; i++ )
619 if ( mpData->pBorders[i].nStyle & RULER_STYLE_INVISIBLE )
620 continue;
622 n1 = mpData->pBorders[i].nPos+mpData->nNullVirOff;
623 n2 = n1+mpData->pBorders[i].nWidth;
625 if ( ((n1 >= nMin) && (n1 <= nMax)) || ((n2 >= nMin) && (n2 <= nMax)) )
627 if ( (n2-n1) > 3 )
629 maVirDev.SetLineColor();
630 maVirDev.SetFillColor( rStyleSettings.GetFaceColor() );
631 ImplVDrawRect( n1, nVirTop, n2, nVirBottom );
633 maVirDev.SetLineColor( rStyleSettings.GetLightColor() );
634 ImplVDrawLine( n1+1, nVirTop, n1+1, nVirBottom );
635 ImplVDrawLine( n1, nVirTop, n2, nVirTop );
636 maVirDev.SetLineColor( rStyleSettings.GetShadowColor() );
637 ImplVDrawLine( n1, nVirTop, n1, nVirBottom );
638 ImplVDrawLine( n1, nVirBottom, n2, nVirBottom );
639 ImplVDrawLine( n2-1, nVirTop, n2-1, nVirBottom );
640 maVirDev.SetLineColor( rStyleSettings.GetDarkShadowColor() );
641 ImplVDrawLine( n2, nVirTop, n2, nVirBottom );
643 if ( mpData->pBorders[i].nStyle & RULER_BORDER_VARIABLE )
645 if ( n2-n1 > RULER_VAR_SIZE+4 )
647 nTemp1 = n1 + (((n2-n1+1)-RULER_VAR_SIZE) / 2);
648 nTemp2 = nVirTop + (((nVirBottom-nVirTop+1)-RULER_VAR_SIZE) / 2);
649 long nTemp3 = nTemp1+RULER_VAR_SIZE-1;
650 long nTemp4 = nTemp2+RULER_VAR_SIZE-1;
651 long nTempY = nTemp2;
653 maVirDev.SetLineColor( rStyleSettings.GetLightColor() );
654 while ( nTempY <= nTemp4 )
656 ImplVDrawLine( nTemp1, nTempY, nTemp3, nTempY );
657 nTempY += 2;
660 nTempY = nTemp2+1;
661 maVirDev.SetLineColor( rStyleSettings.GetShadowColor() );
662 while ( nTempY <= nTemp4 )
664 ImplVDrawLine( nTemp1, nTempY, nTemp3, nTempY );
665 nTempY += 2;
670 if ( mpData->pBorders[i].nStyle & RULER_BORDER_SIZEABLE )
672 if ( n2-n1 > RULER_VAR_SIZE+10 )
674 maVirDev.SetLineColor( rStyleSettings.GetShadowColor() );
675 ImplVDrawLine( n1+4, nVirTop+3, n1+4, nVirBottom-3 );
676 ImplVDrawLine( n2-5, nVirTop+3, n2-5, nVirBottom-3 );
677 maVirDev.SetLineColor( rStyleSettings.GetLightColor() );
678 ImplVDrawLine( n1+5, nVirTop+3, n1+5, nVirBottom-3 );
679 ImplVDrawLine( n2-4, nVirTop+3, n2-4, nVirBottom-3 );
683 else
685 n = n1+((n2-n1)/2);
686 maVirDev.SetLineColor( rStyleSettings.GetShadowColor() );
688 if ( mpData->pBorders[i].nStyle & RULER_BORDER_SNAP )
689 ImplVDrawLine( n, nVirTop, n, nVirBottom );
690 else if ( mpData->pBorders[i].nStyle & RULER_BORDER_MARGIN )
691 ImplVDrawLine( n, nVirTop, n, nVirBottom );
692 else
694 ImplVDrawLine( n-1, nVirTop, n-1, nVirBottom );
695 ImplVDrawLine( n+1, nVirTop, n+1, nVirBottom );
696 maVirDev.SetLineColor();
697 maVirDev.SetFillColor( rStyleSettings.GetWindowColor() );
698 ImplVDrawRect( n, nVirTop, n, nVirBottom );
705 // -----------------------------------------------------------------------
707 void Ruler::ImplDrawIndent( const Polygon& rPoly, sal_uInt16 nStyle )
709 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
711 if ( nStyle & RULER_STYLE_INVISIBLE )
712 return;
714 maVirDev.SetLineColor( rStyleSettings.GetDarkShadowColor() );
715 maVirDev.SetFillColor( rStyleSettings.GetWorkspaceColor() );
716 maVirDev.DrawPolygon( rPoly );
719 // -----------------------------------------------------------------------
721 void Ruler::ImplDrawIndents( long nMin, long nMax, long nVirTop, long nVirBottom )
723 sal_uInt16 j;
724 long n;
725 long nIndentHeight = (mnVirHeight/2) - 1;
726 long nIndentWidth2 = nIndentHeight-3;
727 Polygon aPoly( 5 );
729 for ( j = 0; j < mpData->nIndents; j++ )
731 if ( mpData->pIndents[j].nStyle & RULER_STYLE_INVISIBLE )
732 continue;
734 sal_uInt16 nStyle = mpData->pIndents[j].nStyle;
735 sal_uInt16 nIndentStyle = nStyle & RULER_INDENT_STYLE;
737 n = mpData->pIndents[j].nPos+mpData->nNullVirOff;
739 if ( (n >= nMin) && (n <= nMax) )
741 if(nIndentStyle == RULER_INDENT_BORDER)
743 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
744 maVirDev.SetLineColor( rStyleSettings.GetShadowColor() );
745 ImplVDrawLine( n, nVirTop+1, n, nVirBottom-1 );
747 else if ( nIndentStyle == RULER_INDENT_BOTTOM )
749 aPoly.SetPoint( Point( n+0, nVirBottom-nIndentHeight ), 0 );
750 aPoly.SetPoint( Point( n-nIndentWidth2, nVirBottom-3 ), 1 );
751 aPoly.SetPoint( Point( n-nIndentWidth2, nVirBottom ), 2 );
752 aPoly.SetPoint( Point( n+nIndentWidth2, nVirBottom ), 3 );
753 aPoly.SetPoint( Point( n+nIndentWidth2, nVirBottom-3 ), 4 );
755 else
757 aPoly.SetPoint( Point( n+0, nVirTop+nIndentHeight ), 0 );
758 aPoly.SetPoint( Point( n-nIndentWidth2, nVirTop+3 ), 1 );
759 aPoly.SetPoint( Point( n-nIndentWidth2, nVirTop ), 2 );
760 aPoly.SetPoint( Point( n+nIndentWidth2, nVirTop ), 3 );
761 aPoly.SetPoint( Point( n+nIndentWidth2, nVirTop+3 ), 4 );
764 if(0 == (mnWinStyle & WB_HORZ))
766 Point aTmp;
767 for(sal_uInt16 i = 0; i < 5; i++)
769 aTmp = aPoly[i];
770 Point aSet(nVirBottom - aTmp.Y(), aTmp.X());
771 aPoly[i] = aSet;
774 if(RULER_INDENT_BORDER != nIndentStyle)
775 ImplDrawIndent( aPoly, nStyle );
780 // -----------------------------------------------------------------------
782 static void ImplCenterTabPos( Point& rPos, sal_uInt16 nTabStyle )
784 sal_Bool bRTL = 0 != (nTabStyle & RULER_TAB_RTL);
785 nTabStyle &= RULER_TAB_STYLE;
786 rPos.Y() += RULER_TAB_HEIGHT/2;
787 if ( (!bRTL && nTabStyle == RULER_TAB_LEFT) ||( bRTL && nTabStyle == RULER_TAB_RIGHT))
788 rPos.X() -= RULER_TAB_WIDTH/2;
789 else if ( (!bRTL && nTabStyle == RULER_TAB_RIGHT) ||( bRTL && nTabStyle == RULER_TAB_LEFT))
790 rPos.X() += RULER_TAB_WIDTH/2;
793 // -----------------------------------------------------------------------
794 static void lcl_RotateRect_Impl(Rectangle& rRect, const long nReference, sal_Bool bRightAligned)
796 if(!rRect.IsEmpty())
798 Rectangle aTmp(rRect);
799 rRect.Top() = aTmp.Left();
800 rRect.Bottom() = aTmp.Right();
801 rRect.Left() = aTmp.Top();
802 rRect.Right() = aTmp.Bottom();
803 if(bRightAligned)
805 long nRef = 2 * nReference;
806 rRect.Left() = nRef - rRect.Left();
807 rRect.Right() = nRef - rRect.Right();
811 // -----------------------------------------------------------------------
813 static void ImplDrawRulerTab( OutputDevice* pDevice,
814 const Point& rPos, sal_uInt16 nStyle, WinBits nWinBits )
816 if ( nStyle & RULER_STYLE_INVISIBLE )
817 return;
819 sal_uInt16 nTabStyle = nStyle & RULER_TAB_STYLE;
820 sal_Bool bRTL = 0 != (nStyle & RULER_TAB_RTL);
821 Rectangle aRect1, aRect2, aRect3;
822 aRect3.SetEmpty();
823 if ( nTabStyle == RULER_TAB_DEFAULT )
825 aRect1.Left() = rPos.X() - RULER_TAB_DWIDTH2 + 1 ;
826 aRect1.Top() = rPos.Y() - RULER_TAB_DHEIGHT2 + 1 ;
827 aRect1.Right() = rPos.X() - RULER_TAB_DWIDTH2 + RULER_TAB_DWIDTH ;
828 aRect1.Bottom() = rPos.Y();
829 aRect2.Left() = rPos.X() - RULER_TAB_DWIDTH2 + RULER_TAB_DWIDTH3;
830 aRect2.Top() = rPos.Y() - RULER_TAB_DHEIGHT + 1;
831 aRect2.Right() = rPos.X() - RULER_TAB_DWIDTH2 + RULER_TAB_DWIDTH3 + RULER_TAB_DWIDTH4 - 1;
832 aRect2.Bottom() = rPos.Y();
835 else if ( (!bRTL && nTabStyle == RULER_TAB_LEFT) ||( bRTL && nTabStyle == RULER_TAB_RIGHT))
837 aRect1.Left() = rPos.X();
838 aRect1.Top() = rPos.Y() - RULER_TAB_HEIGHT2 + 1;
839 aRect1.Right() = rPos.X() + RULER_TAB_WIDTH - 1;
840 aRect1.Bottom() = rPos.Y();
841 aRect2.Left() = rPos.X();
842 aRect2.Top() = rPos.Y() - RULER_TAB_HEIGHT + 1;
843 aRect2.Right() = rPos.X() + RULER_TAB_WIDTH2 - 1;
844 aRect2.Bottom() = rPos.Y();
846 else if ( (!bRTL && nTabStyle == RULER_TAB_RIGHT) ||( bRTL && nTabStyle == RULER_TAB_LEFT))
848 aRect1.Left() = rPos.X() - RULER_TAB_WIDTH + 1;
849 aRect1.Top() = rPos.Y() - RULER_TAB_HEIGHT2 + 1;
850 aRect1.Right() = rPos.X();
851 aRect1.Bottom() = rPos.Y();
852 aRect2.Left() = rPos.X() - RULER_TAB_WIDTH2 + 1;
853 aRect2.Top() = rPos.Y() - RULER_TAB_HEIGHT + 1;
854 aRect2.Right() = rPos.X();
855 aRect2.Bottom() = rPos.Y();
857 else
859 aRect1.Left() = rPos.X() - RULER_TAB_CWIDTH2 + 1;
860 aRect1.Top() = rPos.Y() - RULER_TAB_HEIGHT2 + 1;
861 aRect1.Right() = rPos.X() - RULER_TAB_CWIDTH2 + RULER_TAB_CWIDTH;
862 aRect1.Bottom() = rPos.Y();
863 aRect2.Left() = rPos.X() - RULER_TAB_CWIDTH2 + RULER_TAB_CWIDTH3;
864 aRect2.Top() = rPos.Y() - RULER_TAB_HEIGHT + 1;
865 aRect2.Right() = rPos.X() - RULER_TAB_CWIDTH2 + RULER_TAB_CWIDTH3 + RULER_TAB_CWIDTH4 - 1;
866 aRect2.Bottom() = rPos.Y();
868 if ( nTabStyle == RULER_TAB_DECIMAL )
870 aRect3.Left() = rPos.X() - RULER_TAB_CWIDTH2 + RULER_TAB_CWIDTH - 1;
871 aRect3.Top() = rPos.Y() - RULER_TAB_HEIGHT + 1 + 1;
872 aRect3.Right() = rPos.X() - RULER_TAB_CWIDTH2 + RULER_TAB_CWIDTH;
873 aRect3.Bottom()= rPos.Y() - RULER_TAB_HEIGHT + 1 + 2 ;
876 if( 0 == (nWinBits&WB_HORZ) )
878 sal_Bool bRightAligned = 0 != (nWinBits&WB_RIGHT_ALIGNED);
879 lcl_RotateRect_Impl(aRect1, rPos.Y(), bRightAligned);
880 lcl_RotateRect_Impl(aRect2, rPos.Y(), bRightAligned);
881 lcl_RotateRect_Impl(aRect3, rPos.Y(), bRightAligned);
883 pDevice->DrawRect( aRect1 );
884 pDevice->DrawRect( aRect2 );
885 if(!aRect2.IsEmpty())
886 pDevice->DrawRect( aRect3 );
890 // -----------------------------------------------------------------------
892 void Ruler::ImplDrawTab( OutputDevice* pDevice, const Point& rPos, sal_uInt16 nStyle )
894 if ( nStyle & RULER_STYLE_INVISIBLE )
895 return;
897 pDevice->SetLineColor();
898 if ( nStyle & RULER_STYLE_DONTKNOW )
899 pDevice->SetFillColor( GetSettings().GetStyleSettings().GetFaceColor() );
900 else
901 pDevice->SetFillColor( GetSettings().GetStyleSettings().GetDarkShadowColor() );
903 if(mpData->bTextRTL)
904 nStyle |= RULER_TAB_RTL;
905 ImplDrawRulerTab( pDevice, rPos, nStyle, GetStyle());
908 // -----------------------------------------------------------------------
910 void Ruler::ImplDrawTabs( long nMin, long nMax, long nVirTop, long nVirBottom )
912 for ( sal_uInt16 i = 0; i < mpData->nTabs; i++ )
914 if ( mpData->pTabs[i].nStyle & RULER_STYLE_INVISIBLE )
915 continue;
917 long n;
918 n = mpData->pTabs[i].nPos;
919 n += +mpData->nNullVirOff;
920 long nTopBottom = GetStyle() & WB_RIGHT_ALIGNED ? nVirTop : nVirBottom;
921 if ( (n >= nMin) && (n <= nMax) )
922 ImplDrawTab( &maVirDev, Point( n, nTopBottom ), mpData->pTabs[i].nStyle );
926 // -----------------------------------------------------------------------
928 void Ruler::ImplInitSettings( sal_Bool bFont,
929 sal_Bool bForeground, sal_Bool bBackground )
931 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
933 if ( bFont )
935 Font aFont;
936 aFont = rStyleSettings.GetToolFont();
937 if ( IsControlFont() )
938 aFont.Merge( GetControlFont() );
939 SetZoomedPointFont( aFont );
942 if ( bForeground || bFont )
944 Color aColor;
945 if ( IsControlForeground() )
946 aColor = GetControlForeground();
947 else
948 aColor = rStyleSettings.GetDarkShadowColor();
949 SetTextColor( aColor );
950 SetTextFillColor();
953 if ( bBackground )
955 Color aColor;
956 if ( IsControlBackground() )
957 aColor = GetControlBackground();
958 else
959 aColor = rStyleSettings.GetWorkspaceColor();
960 SetBackground( aColor );
963 maVirDev.SetSettings( GetSettings() );
964 maVirDev.SetBackground( GetBackground() );
965 Font aFont = GetFont();
966 if ( mnWinStyle & WB_VERT )
967 aFont.SetOrientation( 900 );
968 maVirDev.SetFont( aFont );
969 maVirDev.SetTextColor( GetTextColor() );
970 maVirDev.SetTextFillColor( GetTextFillColor() );
973 // -----------------------------------------------------------------------
975 void Ruler::ImplCalc()
977 // Offset berechnen
978 mpData->nRulVirOff = mnWinOff + mpData->nPageOff;
979 if ( mpData->nRulVirOff > mnVirOff )
980 mpData->nRulVirOff -= mnVirOff;
981 else
982 mpData->nRulVirOff = 0;
983 long nRulWinOff = mpData->nRulVirOff+mnVirOff;
985 // Nicht sichtbaren Bereich der Page berechnen
986 long nNotVisPageWidth;
987 if ( mpData->nPageOff < 0 )
989 nNotVisPageWidth = -(mpData->nPageOff);
990 if ( nRulWinOff < mnWinOff )
991 nNotVisPageWidth -= mnWinOff-nRulWinOff;
993 else
994 nNotVisPageWidth = 0;
996 // Breite berechnen
997 if ( mnWinStyle & WB_HORZ )
999 if ( mbAutoWinWidth )
1000 mnWinWidth = mnWidth - mnVirOff;
1001 if ( mpData->bAutoPageWidth )
1002 mpData->nPageWidth = mnWinWidth;
1003 mpData->nRulWidth = std::min( mnWinWidth, mpData->nPageWidth-nNotVisPageWidth );
1004 if ( nRulWinOff+mpData->nRulWidth > mnWidth )
1005 mpData->nRulWidth = mnWidth-nRulWinOff;
1007 else
1009 if ( mbAutoWinWidth )
1010 mnWinWidth = mnHeight - mnVirOff;
1011 if ( mpData->bAutoPageWidth )
1012 mpData->nPageWidth = mnWinWidth;
1013 mpData->nRulWidth = std::min( mnWinWidth, mpData->nPageWidth-nNotVisPageWidth );
1014 if ( nRulWinOff+mpData->nRulWidth > mnHeight )
1015 mpData->nRulWidth = mnHeight-nRulWinOff;
1018 mbCalc = sal_False;
1021 // -----------------------------------------------------------------------
1023 void Ruler::ImplFormat()
1025 // Wenn schon formatiert ist, brauchen wir es nicht nochmal
1026 if ( !mbFormat )
1027 return;
1029 // Wenn Fenster noch keine Groesse hat, brauchen wir noch nichts machen
1030 if ( !mnVirWidth )
1031 return;
1033 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
1034 long nP1; // Pixel-Position von Page1
1035 long nP2; // Pixel-Position von Page2
1036 long nM1; // Pixel-Position von Margin1
1037 long nM2; // Pixel-Position von Margin2
1038 long nVirTop; // Obere/Linke-Kante bei Ausgabe
1039 long nVirBottom; // Untere/Rechte-Kante bei Ausgabe
1040 long nVirLeft; // Linke/Obere-Kante bei Ausgabe
1041 long nVirRight; // Rechte/Untere-Kante bei Ausgabe
1042 long nNullVirOff; // Fuer schnellere Berechnung
1044 // Werte berechnen
1045 if ( mbCalc )
1046 ImplCalc();
1047 mpData->nNullVirOff = mnWinOff+mpData->nPageOff+mpData->nNullOff-mnVirOff;
1048 nNullVirOff = mpData->nNullVirOff;
1049 nVirLeft = mpData->nRulVirOff;
1050 nVirRight = nVirLeft+mpData->nRulWidth-1;
1051 nVirTop = 0;
1052 nVirBottom = mnVirHeight-1;
1054 if ( !IsReallyVisible() )
1055 return;
1057 Size aVirDevSize;
1059 // initialize VirtualDevice
1060 if ( mnWinStyle & WB_HORZ )
1062 aVirDevSize.Width() = mnVirWidth;
1063 aVirDevSize.Height() = mnVirHeight;
1065 else
1067 aVirDevSize.Height() = mnVirWidth;
1068 aVirDevSize.Width() = mnVirHeight;
1070 if ( aVirDevSize != maVirDev.GetOutputSizePixel() )
1071 maVirDev.SetOutputSizePixel( aVirDevSize, sal_True );
1072 else
1073 maVirDev.Erase();
1075 // Raender berechnen
1076 if ( !(mpData->nMargin1Style & RULER_STYLE_INVISIBLE) )
1078 nM1 = mpData->nMargin1+nNullVirOff;
1079 if ( mpData->bAutoPageWidth )
1081 nP1 = nVirLeft;
1082 if ( nM1 < nVirLeft )
1083 nP1--;
1085 else
1086 nP1 = nNullVirOff-mpData->nNullOff;
1088 else
1090 nM1 = nVirLeft-1;
1091 nP1 = nM1;
1093 if ( !(mpData->nMargin2Style & RULER_STYLE_INVISIBLE) )
1095 nM2 = mpData->nMargin2+nNullVirOff;
1096 if ( mpData->bAutoPageWidth )
1098 nP2 = nVirRight;
1099 if ( nM2 > nVirRight )
1100 nP2++;
1102 else
1103 nP2 = nNullVirOff-mpData->nNullOff+mpData->nPageWidth;
1104 if ( nM2 > nP2 )
1105 nM2 = nP2;
1107 else
1109 nM2 = nVirRight+1;
1110 nP2 = nM2;
1113 // Obere/untere Kante ausgeben
1114 maVirDev.SetLineColor( rStyleSettings.GetShadowColor() );
1115 ImplVDrawLine( nVirLeft, nVirTop+1, nM1, nVirTop+1 ); //top left line
1116 ImplVDrawLine( nM2, nVirTop+1, nP2 -1, nVirTop+1 ); //top right line
1118 // Jetzt wird zwischen dem Schatten ausgegeben
1119 nVirTop++;
1120 nVirBottom--;
1122 // Margin1, Margin2 und Zwischenraum ausgeben
1123 maVirDev.SetLineColor();
1124 maVirDev.SetFillColor( rStyleSettings.GetWorkspaceColor() );
1125 if ( nM1 > nVirLeft )
1126 ImplVDrawRect( nP1, nVirTop+1, nM1, nVirBottom ); //left gray rectangle
1127 if ( nM2 < nP2 )
1128 ImplVDrawRect( nM2, nVirTop+1, nP2, nVirBottom ); //right gray rectangle
1129 if ( nM2-nM1 > 0 )
1131 maVirDev.SetFillColor( rStyleSettings.GetWindowColor() );
1132 ImplVDrawRect( nM1+1, nVirTop, nM2-1, nVirBottom ); //center rectangle
1134 maVirDev.SetLineColor( rStyleSettings.GetShadowColor() );
1135 if ( nM1 > nVirLeft )
1137 ImplVDrawLine( nM1, nVirTop+1, nM1, nVirBottom );//right line of the left rectangle
1138 ImplVDrawLine( nP1, nVirBottom, nM1, nVirBottom );//bottom line of the left rectangle
1139 if ( nP1 >= nVirLeft )
1141 ImplVDrawLine( nP1, nVirTop+1, nP1, nVirBottom );//left line of the left rectangle
1142 ImplVDrawLine( nP1, nVirBottom, nP1+1, nVirBottom );//?
1145 if ( nM2 < nP2 )
1147 ImplVDrawLine( nM2, nVirBottom, nP2-1, nVirBottom );//bottom line of the right rectangle
1148 ImplVDrawLine( nM2, nVirTop+1, nM2, nVirBottom );//left line of the right rectangle
1149 if ( nP2 <= nVirRight+1 )
1150 ImplVDrawLine( nP2-1, nVirTop+1, nP2-1, nVirBottom );//right line of the right rectangle
1153 // Lineal-Beschriftung (nur wenn keine Bemassungspfeile)
1154 long nMin = nVirLeft;
1155 long nMax = nP2;
1156 long nStart = mpData->bTextRTL ? mpData->nMargin2 + nNullVirOff : nNullVirOff;
1157 long nCenter = nVirTop+((nVirBottom-nVirTop)/2);
1159 // Nicht Schatten uebermalen
1160 if ( nP1 > nVirLeft )
1161 nMin++;
1162 if ( nP2 < nVirRight )
1163 nMax--;
1165 // Draw captions
1166 ImplDrawTicks( nMin, nMax, nStart, nCenter );
1168 // Draw borders
1169 if ( mpData->pBorders )
1170 ImplDrawBorders( nVirLeft, nP2, nVirTop, nVirBottom );
1172 // Draw indents
1173 if ( mpData->pIndents )
1174 ImplDrawIndents( nVirLeft, nP2, nVirTop-1, nVirBottom+1 );
1176 // Tabs
1177 if ( mpData->pTabs )
1179 ImplDrawTabs( nVirLeft, nP2, nVirTop-1, nVirBottom+1 );
1182 // Wir haben formatiert
1183 mbFormat = sal_False;
1186 // -----------------------------------------------------------------------
1188 void Ruler::ImplInitExtraField( sal_Bool bUpdate )
1190 Size aWinSize = GetOutputSizePixel();
1192 // Extra-Field beruecksichtigen
1193 if ( mnWinStyle & WB_EXTRAFIELD )
1195 maExtraRect.Left() = RULER_OFF;
1196 maExtraRect.Top() = RULER_OFF;
1197 maExtraRect.Right() = RULER_OFF+mnVirHeight-1;
1198 maExtraRect.Bottom() = RULER_OFF+mnVirHeight-1;
1199 if(mpData->bTextRTL)
1201 if(mnWinStyle & WB_HORZ)
1202 maExtraRect.Move(aWinSize.Width() - maExtraRect.GetWidth() - maExtraRect.Left(), 0);
1203 else
1204 maExtraRect.Move(0, aWinSize.Height() - maExtraRect.GetHeight() - maExtraRect.Top());
1205 mnVirOff = 0;
1207 else
1208 mnVirOff = maExtraRect.Right()+1;
1211 else
1213 maExtraRect.SetEmpty();
1214 mnVirOff = 0;
1217 // mnVirWidth depends on mnVirOff
1218 if ( (mnVirWidth > RULER_MIN_SIZE) ||
1219 ((aWinSize.Width() > RULER_MIN_SIZE) && (aWinSize.Height() > RULER_MIN_SIZE)) )
1221 if ( mnWinStyle & WB_HORZ )
1222 mnVirWidth = aWinSize.Width()-mnVirOff;
1223 else
1224 mnVirWidth = aWinSize.Height()-mnVirOff;
1226 if ( mnVirWidth < RULER_MIN_SIZE )
1227 mnVirWidth = 0;
1230 if ( bUpdate )
1232 mbCalc = sal_True;
1233 mbFormat = sal_True;
1234 Invalidate();
1238 // -----------------------------------------------------------------------
1240 void Ruler::ImplDraw()
1242 if ( mbFormat )
1243 ImplFormat();
1245 if ( IsReallyVisible() )
1247 // Lineal ueber das VirtualDevice ausgeben
1248 Point aOffPos;
1249 Size aVirDevSize = maVirDev.GetOutputSizePixel();
1250 // Size aVirDevSize2 = maVirDev.GetOutputSizePixel();
1251 if ( mnWinStyle & WB_HORZ )
1253 aOffPos.X() = mnVirOff;
1254 if(mpData->bTextRTL)
1255 aVirDevSize.Width() -= maExtraRect.GetWidth();
1257 // else
1258 // aVirDevSize.Width() -= mnVirOff;
1259 aOffPos.Y() = RULER_OFF;
1261 else
1263 aOffPos.X() = RULER_OFF;
1264 aOffPos.Y() = mnVirOff;
1265 // else
1266 // aVirDevSize.Height() -= mnVirOff;
1268 DrawOutDev( aOffPos, aVirDevSize, Point(), aVirDevSize, maVirDev );
1270 // Positionslinien neu malen
1271 ImplInvertLines( sal_True );
1275 // -----------------------------------------------------------------------
1277 void Ruler::ImplDrawExtra( sal_Bool bPaint )
1279 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
1280 Rectangle aRect = maExtraRect;
1281 sal_Bool bEraseRect = sal_False;
1283 aRect.Left() += 2;
1284 aRect.Top() += 2;
1285 aRect.Right() -= 2;
1286 aRect.Bottom() -= 2;
1288 if ( !bPaint && !(mnExtraStyle & RULER_STYLE_HIGHLIGHT) )
1290 SetFillColor( rStyleSettings.GetWorkspaceColor() );
1291 bEraseRect = sal_True;
1293 else
1295 if ( mnExtraStyle & RULER_STYLE_HIGHLIGHT )
1297 SetFillColor( rStyleSettings.GetCheckedColor() );
1298 bEraseRect = sal_True;
1302 if ( bEraseRect )
1304 SetLineColor();
1305 DrawRect( aRect );
1308 // Inhalt ausgeben
1309 if ( meExtraType == RULER_EXTRA_NULLOFFSET )
1311 SetLineColor( rStyleSettings.GetButtonTextColor() );
1312 DrawLine( Point( aRect.Left()+1, aRect.Top()+4 ),
1313 Point( aRect.Right()-1, aRect.Top()+4 ) );
1314 DrawLine( Point( aRect.Left()+4, aRect.Top()+1 ),
1315 Point( aRect.Left()+4, aRect.Bottom()-1 ) );
1317 else if ( meExtraType == RULER_EXTRA_TAB )
1319 sal_uInt16 nTabStyle = mnExtraStyle & RULER_TAB_STYLE;
1320 if(mpData->bTextRTL)
1321 nTabStyle |= RULER_TAB_RTL;
1322 Point aCenter = aRect.Center();
1323 Point aDraw(aCenter);
1324 ImplCenterTabPos( aDraw, nTabStyle );
1325 WinBits nWinBits = GetStyle();
1326 if(0 == (nWinBits&WB_HORZ) )
1328 if(0 != (nWinBits&WB_RIGHT_ALIGNED))
1329 aDraw.Y() = 2 * aCenter.Y() - aDraw.Y();
1330 if(mpData->bTextRTL)
1332 long nTemp = aDraw.X();
1333 aDraw.X() = aDraw.Y();
1334 aDraw.Y() = nTemp;
1337 ImplDrawTab( this, aDraw, nTabStyle );
1341 // -----------------------------------------------------------------------
1343 void Ruler::ImplUpdate( sal_Bool bMustCalc )
1345 // Hier schon Linien loeschen, damit Sie vor dem Neuberechnen schon
1346 // geloscht sind, da danach die alten Positionen nicht mehr bestimmt
1347 // werden koennen
1348 if ( !mbFormat )
1349 ImplInvertLines();
1351 // Flags setzen
1352 if ( bMustCalc )
1353 mbCalc = sal_True;
1354 mbFormat = sal_True;
1356 // Wenn wir am Draggen sind, wird nach dem Drag-Handler automatisch
1357 // das Lineal neu upgedatet
1358 if ( mbDrag )
1359 return;
1361 // Gegebenenfalls Update ausloesen
1362 if ( IsReallyVisible() && IsUpdateMode() )
1364 mnUpdateFlags |= RULER_UPDATE_DRAW;
1365 if ( !mnUpdateEvtId )
1366 mnUpdateEvtId = Application::PostUserEvent( LINK( this, Ruler, ImplUpdateHdl ), NULL );
1370 // -----------------------------------------------------------------------
1372 sal_Bool Ruler::ImplHitTest( const Point& rPos, ImplRulerHitTest* pHitTest,
1373 sal_Bool bRequireStyle, sal_uInt16 nRequiredStyle ) const
1375 sal_uInt16 i;
1376 sal_uInt16 nStyle;
1377 long nHitBottom;
1378 long nX;
1379 long nY;
1380 long n1;
1381 long n2;
1383 if ( !mbActive )
1384 return sal_False;
1386 // Position ermitteln
1387 sal_Bool bIsHori = 0 != (mnWinStyle & WB_HORZ);
1388 if ( bIsHori )
1390 nX = rPos.X();
1391 nY = rPos.Y();
1393 else
1395 nX = rPos.Y();
1396 nY = rPos.X();
1398 nHitBottom = mnVirHeight+(RULER_OFF*2);
1400 // #i32608#
1401 pHitTest->nAryPos = 0;
1402 pHitTest->mnDragSize = 0;
1403 pHitTest->bSize = sal_False;
1404 pHitTest->bSizeBar = sal_False;
1406 // Damit ueberstehende Tabs und Einzuege mit beruecksichtigt werden
1407 long nXExtraOff;
1408 if ( mpData->pTabs || mpData->pIndents )
1409 nXExtraOff = (mnVirHeight/2) - 4;
1410 else
1411 nXExtraOff = 0;
1413 // Test auf ausserhalb
1414 nX -= mnVirOff;
1415 long nXTemp = nX;
1416 if ( (nX < mpData->nRulVirOff-nXExtraOff) || (nX > mpData->nRulVirOff+mpData->nRulWidth+nXExtraOff) ||
1417 (nY < 0) || (nY > nHitBottom) )
1419 pHitTest->nPos = 0;
1420 pHitTest->eType = RULER_TYPE_OUTSIDE;
1421 return sal_False;
1424 nX -= mpData->nNullVirOff;
1425 pHitTest->nPos = nX;
1426 pHitTest->eType = RULER_TYPE_DONTKNOW;
1428 // Zuerst die Tabs testen
1429 Rectangle aRect;
1430 if ( mpData->pTabs )
1432 aRect.Bottom() = nHitBottom;
1433 aRect.Top() = aRect.Bottom()-RULER_TAB_HEIGHT-RULER_OFF;
1435 for ( i = mpData->nTabs; i; i-- )
1437 nStyle = mpData->pTabs[i-1].nStyle;
1438 if ( !(nStyle & RULER_STYLE_INVISIBLE) )
1440 nStyle &= RULER_TAB_STYLE;
1442 // Default-Tabs werden nur angezeigt
1443 if ( nStyle != RULER_TAB_DEFAULT )
1445 n1 = mpData->pTabs[i-1].nPos;
1447 if ( nStyle == RULER_TAB_LEFT )
1449 aRect.Left() = n1;
1450 aRect.Right() = n1+RULER_TAB_WIDTH-1;
1452 else if ( nStyle == RULER_TAB_RIGHT )
1454 aRect.Right() = n1;
1455 aRect.Left() = n1-RULER_TAB_WIDTH-1;
1457 else
1459 aRect.Left() = n1-RULER_TAB_CWIDTH2+1;
1460 aRect.Right() = n1-RULER_TAB_CWIDTH2+RULER_TAB_CWIDTH;
1463 if ( aRect.IsInside( Point( nX, nY ) ) )
1465 pHitTest->eType = RULER_TYPE_TAB;
1466 pHitTest->nAryPos = i-1;
1467 return sal_True;
1474 // Dann die Einzuege
1475 if ( mpData->pIndents )
1477 long nIndentHeight = (mnVirHeight/2) - 1;
1478 long nIndentWidth2 = nIndentHeight-3;
1480 for ( i = mpData->nIndents; i; i-- )
1482 nStyle = mpData->pIndents[i-1].nStyle;
1483 if ( (! bRequireStyle || nStyle == nRequiredStyle) &&
1484 !(nStyle & RULER_STYLE_INVISIBLE) )
1486 nStyle &= RULER_INDENT_STYLE;
1487 n1 = mpData->pIndents[i-1].nPos;
1489 if ( (nStyle == RULER_INDENT_BOTTOM) ^ (!bIsHori) )
1491 aRect.Left() = n1-nIndentWidth2;
1492 aRect.Right() = n1+nIndentWidth2;
1493 aRect.Top() = nHitBottom-nIndentHeight-RULER_OFF+1;
1494 aRect.Bottom() = nHitBottom;
1496 else
1498 aRect.Left() = n1-nIndentWidth2;
1499 aRect.Right() = n1+nIndentWidth2;
1500 aRect.Top() = 0;
1501 aRect.Bottom() = nIndentHeight+RULER_OFF-1;
1504 if ( aRect.IsInside( Point( nX, nY ) ) )
1506 pHitTest->eType = RULER_TYPE_INDENT;
1507 pHitTest->nAryPos = i-1;
1508 return sal_True;
1514 // Jetzt zaehlt nichts mehr, was links oder rechts uebersteht
1515 if ( (nXTemp < mpData->nRulVirOff) || (nXTemp > mpData->nRulVirOff+mpData->nRulWidth) )
1517 pHitTest->nPos = 0;
1518 pHitTest->eType = RULER_TYPE_OUTSIDE;
1519 return sal_False;
1522 // Danach die Spalten testen
1523 int nBorderTolerance = 1;
1524 if(pHitTest->bExpandTest)
1526 nBorderTolerance++;
1529 for ( i = mpData->nBorders; i; i-- )
1531 n1 = mpData->pBorders[i-1].nPos;
1532 n2 = n1 + mpData->pBorders[i-1].nWidth;
1534 // Spalten werden mit mindestens 3 Pixel breite gezeichnet
1535 if ( !mpData->pBorders[i-1].nWidth )
1537 n1 -= nBorderTolerance;
1538 n2 += nBorderTolerance;
1542 if ( (nX >= n1) && (nX <= n2) )
1544 nStyle = mpData->pBorders[i-1].nStyle;
1545 if ( !(nStyle & RULER_STYLE_INVISIBLE) )
1547 pHitTest->eType = RULER_TYPE_BORDER;
1548 pHitTest->nAryPos = i-1;
1550 if ( !(nStyle & RULER_BORDER_SIZEABLE) )
1552 if ( nStyle & RULER_BORDER_MOVEABLE )
1554 pHitTest->bSizeBar = sal_True;
1555 pHitTest->mnDragSize = RULER_DRAGSIZE_MOVE;
1558 else
1560 long nMOff = RULER_MOUSE_BORDERWIDTH;
1561 while ( nMOff*2 >= (n2-n1-RULER_MOUSE_BORDERMOVE) )
1563 if ( nMOff < 2 )
1565 nMOff = 0;
1566 break;
1568 else
1569 nMOff--;
1572 if ( nX <= n1+nMOff )
1574 pHitTest->bSize = sal_True;
1575 pHitTest->mnDragSize = RULER_DRAGSIZE_1;
1577 else if ( nX >= n2-nMOff )
1579 pHitTest->bSize = sal_True;
1580 pHitTest->mnDragSize = RULER_DRAGSIZE_2;
1582 else
1584 if ( nStyle & RULER_BORDER_MOVEABLE )
1586 pHitTest->bSizeBar = sal_True;
1587 pHitTest->mnDragSize = RULER_DRAGSIZE_MOVE;
1592 return sal_True;
1597 // Und zum Schluss die Raender
1598 int nMarginTolerance = pHitTest->bExpandTest ? nBorderTolerance : RULER_MOUSE_MARGINWIDTH;
1600 if ( (mpData->nMargin1Style & (RULER_MARGIN_SIZEABLE | RULER_STYLE_INVISIBLE)) == RULER_MARGIN_SIZEABLE )
1602 n1 = mpData->nMargin1;
1603 if ( (nX >= n1 - nMarginTolerance) && (nX <= n1 + nMarginTolerance) )
1605 pHitTest->eType = RULER_TYPE_MARGIN1;
1606 pHitTest->bSize = sal_True;
1607 return sal_True;
1610 if ( (mpData->nMargin2Style & (RULER_MARGIN_SIZEABLE | RULER_STYLE_INVISIBLE)) == RULER_MARGIN_SIZEABLE )
1612 n1 = mpData->nMargin2;
1613 if ( (nX >= n1 - nMarginTolerance) && (nX <= n1 + nMarginTolerance) )
1615 pHitTest->eType = RULER_TYPE_MARGIN2;
1616 pHitTest->bSize = sal_True;
1617 return sal_True;
1621 // Jetzt nocheinmal die Tabs testen, nur mit etwas mehr spielraum
1622 if ( mpData->pTabs )
1624 aRect.Top() = RULER_OFF;
1625 aRect.Bottom() = nHitBottom;
1627 for ( i = mpData->nTabs; i; i-- )
1629 nStyle = mpData->pTabs[i-1].nStyle;
1630 if ( !(nStyle & RULER_STYLE_INVISIBLE) )
1632 nStyle &= RULER_TAB_STYLE;
1634 // Default-Tabs werden nur angezeigt
1635 if ( nStyle != RULER_TAB_DEFAULT )
1637 n1 = mpData->pTabs[i-1].nPos;
1639 if ( nStyle == RULER_TAB_LEFT )
1641 aRect.Left() = n1;
1642 aRect.Right() = n1+RULER_TAB_WIDTH-1;
1644 else if ( nStyle == RULER_TAB_RIGHT )
1646 aRect.Right() = n1;
1647 aRect.Left() = n1-RULER_TAB_WIDTH-1;
1649 else
1651 aRect.Left() = n1-RULER_TAB_CWIDTH2+1;
1652 aRect.Right() = n1-RULER_TAB_CWIDTH2+RULER_TAB_CWIDTH;
1655 aRect.Left()--;
1656 aRect.Right()++;
1658 if ( aRect.IsInside( Point( nX, nY ) ) )
1660 pHitTest->eType = RULER_TYPE_TAB;
1661 pHitTest->nAryPos = i-1;
1662 return sal_True;
1669 return sal_False;
1672 // -----------------------------------------------------------------------
1674 sal_Bool Ruler::ImplDocHitTest( const Point& rPos, RulerType eDragType,
1675 ImplRulerHitTest* pHitTest ) const
1677 Point aPos = rPos;
1678 sal_Bool bRequiredStyle = sal_False;
1679 sal_uInt16 nRequiredStyle = 0;
1681 if (eDragType == RULER_TYPE_INDENT)
1683 bRequiredStyle = sal_True;
1684 nRequiredStyle = RULER_INDENT_BOTTOM;
1687 if ( mnWinStyle & WB_HORZ )
1688 aPos.X() += mnWinOff;
1689 else
1690 aPos.Y() += mnWinOff;
1692 if ( (eDragType == RULER_TYPE_INDENT) || (eDragType == RULER_TYPE_DONTKNOW) )
1694 if ( mnWinStyle & WB_HORZ )
1695 aPos.Y() = RULER_OFF+1;
1696 else
1697 aPos.X() = RULER_OFF+1;
1699 // HitTest durchfuehren
1700 if ( ImplHitTest( aPos, pHitTest, bRequiredStyle, nRequiredStyle ) )
1702 if ( (pHitTest->eType == eDragType) || (eDragType == RULER_TYPE_DONTKNOW) )
1703 return sal_True;
1707 if ( (eDragType == RULER_TYPE_INDENT) || (eDragType == RULER_TYPE_TAB) ||
1708 (eDragType == RULER_TYPE_DONTKNOW) )
1710 if ( mnWinStyle & WB_HORZ )
1711 aPos.Y() = mnHeight-RULER_OFF-1;
1712 else
1713 aPos.X() = mnWidth-RULER_OFF-1;
1715 // HitTest durchfuehren
1716 if ( ImplHitTest( aPos, pHitTest, bRequiredStyle, nRequiredStyle ) )
1718 if ( (pHitTest->eType == eDragType) || (eDragType == RULER_TYPE_DONTKNOW) )
1719 return sal_True;
1723 if ( (eDragType == RULER_TYPE_MARGIN1) || (eDragType == RULER_TYPE_MARGIN2) ||
1724 (eDragType == RULER_TYPE_BORDER) || (eDragType == RULER_TYPE_DONTKNOW) )
1726 if ( mnWinStyle & WB_HORZ )
1727 aPos.Y() = RULER_OFF + (mnVirHeight/2);
1728 else
1729 aPos.X() = RULER_OFF + (mnVirHeight/2);
1731 // HitTest durchfuehren
1732 if ( ImplHitTest( aPos, pHitTest ) )
1734 if ( (pHitTest->eType == eDragType) || (eDragType == RULER_TYPE_DONTKNOW) )
1735 return sal_True;
1739 // Auf DontKnow setzen
1740 pHitTest->eType = RULER_TYPE_DONTKNOW;
1742 return sal_False;
1745 // -----------------------------------------------------------------------
1747 sal_Bool Ruler::ImplStartDrag( ImplRulerHitTest* pHitTest, sal_uInt16 nModifier )
1749 // Wenn eine Spalte angeklick wurde, die weder verschiebar noch
1750 // in der Groesse aenderbar ist, brauchen wir auch kein Drag ausloesen
1751 if ( (pHitTest->eType == RULER_TYPE_BORDER) &&
1752 !pHitTest->bSize && !pHitTest->bSizeBar )
1753 return sal_False;
1755 // Dragdaten setzen
1756 meDragType = pHitTest->eType;
1757 mnDragPos = pHitTest->nPos;
1758 mnDragAryPos = pHitTest->nAryPos;
1759 mnDragSize = pHitTest->mnDragSize;
1760 mnDragModifier = nModifier;
1761 *mpDragData = *mpSaveData;
1762 mpData = mpDragData;
1764 // Handler rufen
1765 if ( StartDrag() )
1767 // Wenn der Handler das Draggen erlaubt, dann das Draggen
1768 // initialisieren
1769 ImplInvertLines();
1770 mbDrag = sal_True;
1771 mnStartDragPos = mnDragPos;
1772 StartTracking();
1773 return sal_True;
1775 else
1777 // Ansonsten muessen wir die Daten zuruecksetzen
1778 meDragType = RULER_TYPE_DONTKNOW;
1779 mnDragPos = 0;
1780 mnDragAryPos = 0;
1781 mnDragSize = 0;
1782 mnDragModifier = 0;
1783 mpData = mpSaveData;
1786 return sal_False;
1789 // -----------------------------------------------------------------------
1791 void Ruler::ImplDrag( const Point& rPos )
1793 long nX;
1794 long nY;
1795 long nOutHeight;
1797 if ( mnWinStyle & WB_HORZ )
1799 nX = rPos.X();
1800 nY = rPos.Y();
1801 nOutHeight = mnHeight;
1803 else
1805 nX = rPos.Y();
1806 nY = rPos.X();
1807 nOutHeight = mnWidth;
1810 // X berechnen und einpassen
1811 nX -= mnVirOff;
1812 if ( nX < mpData->nRulVirOff )
1814 nX = mpData->nRulVirOff;
1815 mnDragScroll = RULER_SCROLL_1;
1817 else if ( nX > mpData->nRulVirOff+mpData->nRulWidth )
1819 nX = mpData->nRulVirOff+mpData->nRulWidth;
1820 mnDragScroll = RULER_SCROLL_2;
1822 nX -= mpData->nNullVirOff;
1824 // Wenn oberhalb oder links vom Lineal, dann alte Werte
1825 mbDragDelete = sal_False;
1826 if ( nY < 0 )
1828 if ( !mbDragCanceled )
1830 // Daten wiederherstellen
1831 mbDragCanceled = sal_True;
1832 ImplRulerData aTempData;
1833 aTempData = *mpDragData;
1834 *mpDragData = *mpSaveData;
1835 mbCalc = sal_True;
1836 mbFormat = sal_True;
1838 // Handler rufen
1839 mnDragPos = mnStartDragPos;
1840 Drag();
1842 // Und neu ausgeben (zeitverzoegert)
1843 ImplDraw();
1845 // Daten wieder wie vor dem Cancel herstellen
1846 *mpDragData = aTempData;
1849 else
1851 mbDragCanceled = sal_False;
1853 // +2, damit nicht so schnell die Tabs geloescht werden
1854 if ( nY > nOutHeight+2 )
1855 mbDragDelete = sal_True;
1857 mnDragPos = nX;
1859 // Handler rufen
1860 Drag();
1862 // Und neu ausgeben
1863 if ( mbFormat )
1864 ImplDraw();
1867 mnDragScroll = 0;
1870 // -----------------------------------------------------------------------
1872 void Ruler::ImplEndDrag()
1874 // Werte uebernehmen
1875 if ( mbDragCanceled )
1876 *mpDragData = *mpSaveData;
1877 else
1878 *mpSaveData = *mpDragData;
1879 mpData = mpSaveData;
1880 mbDrag = sal_False;
1882 // Handler rufen
1883 EndDrag();
1885 // Drag-Werte zuruecksetzen
1886 meDragType = RULER_TYPE_DONTKNOW;
1887 mnDragPos = 0;
1888 mnDragAryPos = 0;
1889 mnDragSize = 0;
1890 mbDragCanceled = sal_False;
1891 mbDragDelete = sal_False;
1892 mnDragModifier = 0;
1893 mnDragScroll = 0;
1894 mnStartDragPos = 0;
1896 // Und neu ausgeben
1897 ImplDraw();
1900 // -----------------------------------------------------------------------
1902 IMPL_LINK_NOARG(Ruler, ImplUpdateHdl)
1904 mnUpdateEvtId = 0;
1906 // Feststellen, was upgedatet werden muss
1907 if ( mnUpdateFlags & RULER_UPDATE_DRAW )
1909 mnUpdateFlags = 0;
1910 ImplDraw();
1912 else if ( mnUpdateFlags & RULER_UPDATE_LINES )
1914 mnUpdateFlags = 0;
1915 ImplInvertLines();
1918 return 0;
1921 // -----------------------------------------------------------------------
1923 void Ruler::MouseButtonDown( const MouseEvent& rMEvt )
1925 if ( rMEvt.IsLeft() && !IsTracking() )
1927 Point aMousePos = rMEvt.GetPosPixel();
1928 sal_uInt16 nMouseClicks = rMEvt.GetClicks();
1929 sal_uInt16 nMouseModifier = rMEvt.GetModifier();
1931 // Gegebenenfalls Lineal updaten (damit mit den richtigen Daten
1932 // gearbeitet wird und die Anzeige auch zur Bearbeitung passt)
1933 if ( mbFormat )
1935 ImplDraw();
1936 mnUpdateFlags &= ~RULER_UPDATE_DRAW;
1939 if ( maExtraRect.IsInside( aMousePos ) )
1941 mnExtraClicks = nMouseClicks;
1942 mnExtraModifier = nMouseModifier;
1943 ExtraDown();
1944 mnExtraClicks = 0;
1945 mnExtraModifier = 0;
1947 else
1949 ImplRulerHitTest aHitTest;
1951 if ( nMouseClicks == 1 )
1953 if ( ImplHitTest( aMousePos, &aHitTest ) )
1954 ImplStartDrag( &aHitTest, nMouseModifier );
1955 else
1957 // Position innerhalb des Lineal-Bereiches
1958 if ( aHitTest.eType == RULER_TYPE_DONTKNOW )
1960 mnDragPos = aHitTest.nPos;
1961 Click();
1962 mnDragPos = 0;
1964 // Nocheinmal HitTest durchfuehren, da durch den Click
1965 // zum Beispiel ein neuer Tab gesetzt werden konnte
1966 if ( ImplHitTest( aMousePos, &aHitTest ) )
1967 ImplStartDrag( &aHitTest, nMouseModifier );
1971 else
1973 if ( ImplHitTest( aMousePos, &aHitTest ) )
1975 mnDragPos = aHitTest.nPos;
1976 mnDragAryPos = aHitTest.nAryPos;
1978 meDragType = aHitTest.eType;
1980 DoubleClick();
1982 meDragType = RULER_TYPE_DONTKNOW;
1983 mnDragPos = 0;
1984 mnDragAryPos = 0;
1990 // -----------------------------------------------------------------------
1992 void Ruler::MouseMove( const MouseEvent& rMEvt )
1994 PointerStyle ePtrStyle = POINTER_ARROW;
1996 // Gegebenenfalls Lineal updaten (damit mit den richtigen Daten
1997 // gearbeitet wird und die Anzeige auch zur Bearbeitung passt)
1998 if ( mbFormat )
2000 ImplDraw();
2001 mnUpdateFlags &= ~RULER_UPDATE_DRAW;
2004 ImplRulerHitTest aHitTest;
2005 if ( ImplHitTest( rMEvt.GetPosPixel(), &aHitTest ) )
2007 if ( aHitTest.bSize )
2009 if ( mnWinStyle & WB_HORZ )
2010 ePtrStyle = POINTER_ESIZE;
2011 else
2012 ePtrStyle = POINTER_SSIZE;
2014 else if ( aHitTest.bSizeBar )
2016 if ( mnWinStyle & WB_HORZ )
2017 ePtrStyle = POINTER_HSIZEBAR;
2018 else
2019 ePtrStyle = POINTER_VSIZEBAR;
2023 SetPointer( Pointer( ePtrStyle ) );
2026 // -----------------------------------------------------------------------
2028 void Ruler::Tracking( const TrackingEvent& rTEvt )
2030 if ( rTEvt.IsTrackingEnded() )
2032 // Bei Abbruch, den alten Status wieder herstellen
2033 if ( rTEvt.IsTrackingCanceled() )
2035 mbDragCanceled = sal_True;
2036 mbFormat = sal_True;
2039 ImplEndDrag();
2041 else
2042 ImplDrag( rTEvt.GetMouseEvent().GetPosPixel() );
2045 // -----------------------------------------------------------------------
2047 void Ruler::Paint( const Rectangle& )
2049 ImplDraw();
2051 // Extra-Field beruecksichtigen
2052 if ( mnWinStyle & WB_EXTRAFIELD )
2053 ImplDrawExtra( sal_True );
2056 // -----------------------------------------------------------------------
2058 void Ruler::Resize()
2060 Size aWinSize = GetOutputSizePixel();
2062 long nNewHeight;
2063 if ( mnWinStyle & WB_HORZ )
2065 if ( aWinSize.Height() != mnHeight )
2066 nNewHeight = aWinSize.Height();
2067 else
2068 nNewHeight = 0;
2070 else
2072 if ( aWinSize.Width() != mnWidth )
2073 nNewHeight = aWinSize.Width();
2074 else
2075 nNewHeight = 0;
2078 // Hier schon Linien loeschen
2079 sal_Bool bVisible = IsReallyVisible();
2080 if ( bVisible && mpData->nLines )
2082 ImplInvertLines();
2083 mnUpdateFlags |= RULER_UPDATE_LINES;
2084 if ( !mnUpdateEvtId )
2085 mnUpdateEvtId = Application::PostUserEvent( LINK( this, Ruler, ImplUpdateHdl ), NULL );
2087 mbFormat = sal_True;
2089 // Wenn sich die Hoehe bzw. Breite aendert, dann muessen besimmte Werte
2090 // neu berechnet werden
2091 //extra field should always be updated
2092 ImplInitExtraField( mpData->bTextRTL );
2093 if ( nNewHeight )
2095 mbCalc = sal_True;
2096 mnVirHeight = nNewHeight - mnBorderWidth - (RULER_OFF*2);
2098 else
2100 if ( mpData->bAutoPageWidth )
2101 ImplUpdate( sal_True );
2102 else if ( mbAutoWinWidth )
2103 mbCalc = sal_True;
2106 // Gegebenenfalls ein Teil vom Rand loeschen, da 3D-Effekt/Trennlinie am
2107 // Fensterrand
2108 if ( bVisible )
2110 if ( nNewHeight )
2111 Invalidate();
2112 else if ( mpData->bAutoPageWidth )
2114 // Nur bei AutoPageWidth haben wir rechts einen 3D-Effekt,
2115 // der sich der Fensterbreite anpasst und deshalb neu gezeichnet
2116 // werden muss
2117 Rectangle aRect;
2119 if ( mnWinStyle & WB_HORZ )
2121 if ( mnWidth < aWinSize.Width() )
2122 aRect.Left() = mnWidth-RULER_RESIZE_OFF;
2123 else
2124 aRect.Left() = aWinSize.Width()-RULER_RESIZE_OFF;
2125 aRect.Right() = aRect.Left()+RULER_RESIZE_OFF;
2126 aRect.Top() = RULER_OFF;
2127 aRect.Bottom() = RULER_OFF+mnVirHeight;
2129 else
2131 if ( mnHeight < aWinSize.Height() )
2132 aRect.Top() = mnHeight-RULER_RESIZE_OFF;
2133 else
2134 aRect.Top() = aWinSize.Height()-RULER_RESIZE_OFF;
2135 aRect.Bottom() = aRect.Top()+RULER_RESIZE_OFF;
2136 aRect.Left() = RULER_OFF;
2137 aRect.Right() = RULER_OFF+mnVirHeight;
2140 Invalidate( aRect );
2144 // Neue Groesse merken
2145 mnWidth = aWinSize.Width();
2146 mnHeight = aWinSize.Height();
2149 // -----------------------------------------------------------------------
2151 void Ruler::StateChanged( StateChangedType nType )
2153 Window::StateChanged( nType );
2155 if ( nType == STATE_CHANGE_INITSHOW )
2156 ImplFormat();
2157 else if ( nType == STATE_CHANGE_UPDATEMODE )
2159 if ( IsReallyVisible() && IsUpdateMode() )
2160 ImplDraw();
2162 else if ( (nType == STATE_CHANGE_ZOOM) ||
2163 (nType == STATE_CHANGE_CONTROLFONT) )
2165 ImplInitSettings( sal_True, sal_False, sal_False );
2166 Invalidate();
2168 else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
2170 ImplInitSettings( sal_False, sal_True, sal_False );
2171 Invalidate();
2173 else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
2175 ImplInitSettings( sal_False, sal_False, sal_True );
2176 Invalidate();
2180 // -----------------------------------------------------------------------
2182 void Ruler::DataChanged( const DataChangedEvent& rDCEvt )
2184 Window::DataChanged( rDCEvt );
2186 if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
2187 (rDCEvt.GetType() == DATACHANGED_DISPLAY) ||
2188 (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
2189 ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
2190 (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
2192 mbFormat = sal_True;
2193 ImplInitSettings( sal_True, sal_True, sal_True );
2194 Invalidate();
2198 // -----------------------------------------------------------------------
2200 long Ruler::StartDrag()
2202 if ( maStartDragHdl.IsSet() )
2203 return maStartDragHdl.Call( this );
2204 else
2205 return sal_False;
2208 // -----------------------------------------------------------------------
2210 void Ruler::Drag()
2212 maDragHdl.Call( this );
2215 // -----------------------------------------------------------------------
2217 void Ruler::EndDrag()
2219 maEndDragHdl.Call( this );
2222 // -----------------------------------------------------------------------
2224 void Ruler::Click()
2226 maClickHdl.Call( this );
2229 // -----------------------------------------------------------------------
2231 void Ruler::DoubleClick()
2233 maDoubleClickHdl.Call( this );
2236 // -----------------------------------------------------------------------
2238 void Ruler::ExtraDown()
2240 maExtraDownHdl.Call( this );
2243 // -----------------------------------------------------------------------
2245 void Ruler::Activate()
2247 mbActive = sal_True;
2249 // Positionslinien wieder anzeigen (erst hinter mbActive=sal_True rufen, da
2250 // von ImplInvertLines() ausgewertet wird). Das Zeichnen der Linien
2251 // wird verzoegert, damit im vermutlich noch nicht gepainteten Zustand
2252 // Linien gezeichnet werden.
2253 mnUpdateFlags |= RULER_UPDATE_LINES;
2254 if ( !mnUpdateEvtId )
2255 mnUpdateEvtId = Application::PostUserEvent( LINK( this, Ruler, ImplUpdateHdl ), NULL );
2258 // -----------------------------------------------------------------------
2260 void Ruler::Deactivate()
2262 // Positionslinien loeschen (schon vor mbActive=sal_False rufen, da
2263 // von ImplInvertLines() ausgewertet wird)
2264 ImplInvertLines();
2266 mbActive = sal_False;
2269 // -----------------------------------------------------------------------
2271 sal_Bool Ruler::StartDocDrag( const MouseEvent& rMEvt, RulerType eDragType )
2273 if ( !mbDrag )
2275 Point aMousePos = rMEvt.GetPosPixel();
2276 sal_uInt16 nMouseClicks = rMEvt.GetClicks();
2277 sal_uInt16 nMouseModifier = rMEvt.GetModifier();
2278 ImplRulerHitTest aHitTest;
2279 if(eDragType != RULER_TYPE_DONTKNOW)
2280 aHitTest.bExpandTest = sal_True;
2282 // Gegebenenfalls Lineal updaten (damit mit den richtigen Daten
2283 // gearbeitet wird und die Anzeige auch zur Bearbeitung passt)
2284 if ( mbFormat )
2286 ImplDraw();
2287 mnUpdateFlags &= ~RULER_UPDATE_DRAW;
2290 if ( nMouseClicks == 1 )
2292 if ( ImplDocHitTest( aMousePos, eDragType, &aHitTest ) )
2294 Pointer aPtr;
2296 if ( aHitTest.bSize )
2298 if ( mnWinStyle & WB_HORZ )
2299 aPtr = Pointer( POINTER_ESIZE );
2300 else
2301 aPtr = Pointer( POINTER_SSIZE );
2303 else if ( aHitTest.bSizeBar )
2305 if ( mnWinStyle & WB_HORZ )
2306 aPtr = Pointer( POINTER_HSIZEBAR );
2307 else
2308 aPtr = Pointer( POINTER_VSIZEBAR );
2310 SetPointer( aPtr );
2311 return ImplStartDrag( &aHitTest, nMouseModifier );
2314 else if ( nMouseClicks == 2 )
2316 if ( ImplDocHitTest( aMousePos, eDragType, &aHitTest ) )
2318 mnDragPos = aHitTest.nPos;
2319 mnDragAryPos = aHitTest.nAryPos;
2321 eDragType = aHitTest.eType;
2323 DoubleClick();
2325 eDragType = RULER_TYPE_DONTKNOW;
2326 mnDragPos = 0;
2327 mnDragAryPos = 0;
2329 return sal_True;
2333 return sal_False;
2336 // -----------------------------------------------------------------------
2338 void Ruler::CancelDrag()
2340 if ( mbDrag )
2342 ImplDrag( Point( -1, -1 ) );
2343 ImplEndDrag();
2347 // -----------------------------------------------------------------------
2349 RulerType Ruler::GetType( const Point& rPos, sal_uInt16* pAryPos ) const
2351 ImplRulerHitTest aHitTest;
2353 // Gegebenenfalls Lineal updaten (damit mit den richtigen Daten
2354 // gearbeitet wird und die Anzeige auch zur Bearbeitung passt)
2355 if ( IsReallyVisible() && mbFormat )
2357 ((Ruler*)this)->ImplDraw();
2358 ((Ruler*)this)->mnUpdateFlags &= ~RULER_UPDATE_DRAW;
2361 // HitTest durchfuehren
2362 ImplHitTest( rPos, &aHitTest );
2364 // Werte zurueckgeben
2365 if ( pAryPos )
2366 *pAryPos = aHitTest.nAryPos;
2367 return aHitTest.eType;
2370 // -----------------------------------------------------------------------
2372 void Ruler::SetWinPos( long nNewOff, long nNewWidth )
2374 // Gegebenenfalls werden die Breiten automatisch berechnet
2375 if ( !nNewWidth )
2376 mbAutoWinWidth = sal_True;
2377 else
2378 mbAutoWinWidth = sal_False;
2380 // Werte setzen (werden in ImplFormat gegebenenfalls mitberechnet)
2381 mnWinOff = nNewOff;
2382 mnWinWidth = nNewWidth;
2383 ImplUpdate( sal_True );
2386 // -----------------------------------------------------------------------
2388 void Ruler::SetPagePos( long nNewOff, long nNewWidth )
2390 // Muessen wir ueberhaupt was machen
2391 if ( (mpData->nPageOff == nNewOff) && (mpData->nPageWidth == nNewWidth) )
2392 return;
2394 // Gegebenenfalls werden die Breiten automatisch berechnet
2395 if ( !nNewWidth )
2396 mpData->bAutoPageWidth = sal_True;
2397 else
2398 mpData->bAutoPageWidth = sal_False;
2400 // Werte setzen (werden in ImplFormat gegebenenfalls mitberechnet)
2401 mpData->nPageOff = nNewOff;
2402 mpData->nPageWidth = nNewWidth;
2403 ImplUpdate( sal_True );
2406 // -----------------------------------------------------------------------
2408 void Ruler::SetBorderPos( long nOff )
2410 if ( mnWinStyle & WB_BORDER )
2412 if ( mnBorderOff != nOff )
2414 mnBorderOff = nOff;
2416 if ( IsReallyVisible() && IsUpdateMode() )
2417 Invalidate();
2422 // -----------------------------------------------------------------------
2424 void Ruler::SetUnit( FieldUnit eNewUnit )
2426 if ( meUnit != eNewUnit )
2428 meUnit = eNewUnit;
2429 switch ( meUnit )
2431 case FUNIT_MM:
2432 mnUnitIndex = RULER_UNIT_MM;
2433 break;
2434 case FUNIT_CM:
2435 mnUnitIndex = RULER_UNIT_CM;
2436 break;
2437 case FUNIT_M:
2438 mnUnitIndex = RULER_UNIT_M;
2439 break;
2440 case FUNIT_KM:
2441 mnUnitIndex = RULER_UNIT_KM;
2442 break;
2443 case FUNIT_INCH:
2444 mnUnitIndex = RULER_UNIT_INCH;
2445 break;
2446 case FUNIT_FOOT:
2447 mnUnitIndex = RULER_UNIT_FOOT;
2448 break;
2449 case FUNIT_MILE:
2450 mnUnitIndex = RULER_UNIT_MILE;
2451 break;
2452 case FUNIT_POINT:
2453 mnUnitIndex = RULER_UNIT_POINT;
2454 break;
2455 case FUNIT_PICA:
2456 mnUnitIndex = RULER_UNIT_PICA;
2457 break;
2458 case FUNIT_CHAR:
2459 mnUnitIndex = RULER_UNIT_CHAR;
2460 break;
2461 case FUNIT_LINE:
2462 mnUnitIndex = RULER_UNIT_LINE;
2463 break;
2464 default:
2465 SAL_WARN( "svtools.control", "Ruler::SetUnit() - Wrong Unit" );
2466 break;
2469 maMapMode.SetMapUnit( aImplRulerUnitTab[mnUnitIndex].eMapUnit );
2470 ImplUpdate();
2474 // -----------------------------------------------------------------------
2476 void Ruler::SetZoom( const Fraction& rNewZoom )
2478 DBG_ASSERT( rNewZoom.GetNumerator(), "Ruler::SetZoom() with scale 0 is not allowed" );
2480 if ( maZoom != rNewZoom )
2482 maZoom = rNewZoom;
2483 maMapMode.SetScaleX( maZoom );
2484 maMapMode.SetScaleY( maZoom );
2485 ImplUpdate();
2489 // -----------------------------------------------------------------------
2491 void Ruler::SetExtraType( RulerExtra eNewExtraType, sal_uInt16 nStyle )
2493 if ( mnWinStyle & WB_EXTRAFIELD )
2495 meExtraType = eNewExtraType;
2496 mnExtraStyle = nStyle;
2497 if ( IsReallyVisible() && IsUpdateMode() )
2498 ImplDrawExtra( sal_False );
2502 // -----------------------------------------------------------------------
2504 void Ruler::SetNullOffset( long nPos )
2506 if ( mpData->nNullOff != nPos )
2508 mpData->nNullOff = nPos;
2509 ImplUpdate();
2513 // -----------------------------------------------------------------------
2515 void Ruler::SetMargin1( long nPos, sal_uInt16 nMarginStyle )
2517 if ( (mpData->nMargin1 != nPos) || (mpData->nMargin1Style != nMarginStyle) )
2519 mpData->nMargin1 = nPos;
2520 mpData->nMargin1Style = nMarginStyle;
2521 ImplUpdate();
2525 // -----------------------------------------------------------------------
2527 void Ruler::SetMargin2( long nPos, sal_uInt16 nMarginStyle )
2529 DBG_ASSERT( (nPos >= mpData->nMargin1) ||
2530 (mpData->nMargin1Style & RULER_STYLE_INVISIBLE) ||
2531 (mpData->nMargin2Style & RULER_STYLE_INVISIBLE),
2532 "Ruler::SetMargin2() - Margin2 < Margin1" );
2534 if ( (mpData->nMargin2 != nPos) || (mpData->nMargin2Style != nMarginStyle) )
2536 mpData->nMargin2 = nPos;
2537 mpData->nMargin2Style = nMarginStyle;
2538 ImplUpdate();
2542 // -----------------------------------------------------------------------
2544 void Ruler::SetLines( sal_uInt16 n, const RulerLine* pLineAry )
2546 // To determine if what has changed
2547 if ( mpData->nLines == n )
2549 sal_uInt16 i = n;
2550 const RulerLine* pAry1 = mpData->pLines;
2551 const RulerLine* pAry2 = pLineAry;
2552 while ( i )
2554 if ( (pAry1->nPos != pAry2->nPos) ||
2555 (pAry1->nStyle != pAry2->nStyle) )
2556 break;
2557 pAry1++;
2558 pAry2++;
2559 i--;
2561 if ( !i )
2562 return;
2565 // New values and new share issue
2566 sal_Bool bMustUpdate;
2567 if ( IsReallyVisible() && IsUpdateMode() )
2568 bMustUpdate = sal_True;
2569 else
2570 bMustUpdate = sal_False;
2572 // Delete old lines
2573 if ( bMustUpdate )
2574 ImplInvertLines();
2576 // New data set
2577 if ( !n || !pLineAry )
2579 if ( !mpData->pLines )
2580 return;
2581 delete[] mpData->pLines;
2582 mpData->nLines = 0;
2583 mpData->pLines = NULL;
2585 else
2587 if ( mpData->nLines != n )
2589 delete[] mpData->pLines;
2590 mpData->nLines = n;
2591 mpData->pLines = new RulerLine[n];
2594 memcpy( mpData->pLines, pLineAry, n*sizeof( RulerLine ) );
2596 // Linien neu ausgeben
2597 if ( bMustUpdate )
2598 ImplInvertLines();
2602 // -----------------------------------------------------------------------
2604 void Ruler::SetBorders( sal_uInt16 n, const RulerBorder* pBrdAry )
2606 if ( !n || !pBrdAry )
2608 if ( !mpData->pBorders )
2609 return;
2610 delete[] mpData->pBorders;
2611 mpData->nBorders = 0;
2612 mpData->pBorders = NULL;
2614 else
2616 if ( mpData->nBorders != n )
2618 delete[] mpData->pBorders;
2619 mpData->nBorders = n;
2620 mpData->pBorders = new RulerBorder[n];
2622 else
2624 sal_uInt16 i = n;
2625 const RulerBorder* pAry1 = mpData->pBorders;
2626 const RulerBorder* pAry2 = pBrdAry;
2627 while ( i )
2629 if ( (pAry1->nPos != pAry2->nPos) ||
2630 (pAry1->nWidth != pAry2->nWidth) ||
2631 (pAry1->nStyle != pAry2->nStyle) )
2632 break;
2633 pAry1++;
2634 pAry2++;
2635 i--;
2637 if ( !i )
2638 return;
2641 memcpy( mpData->pBorders, pBrdAry, n*sizeof( RulerBorder ) );
2644 ImplUpdate();
2647 // -----------------------------------------------------------------------
2649 void Ruler::SetIndents( sal_uInt16 n, const RulerIndent* pIndentAry )
2652 if ( !n || !pIndentAry )
2654 if ( !mpData->pIndents )
2655 return;
2656 delete[] mpData->pIndents;
2657 mpData->nIndents = 0;
2658 mpData->pIndents = NULL;
2660 else
2662 if ( mpData->nIndents != n )
2664 delete[] mpData->pIndents;
2665 mpData->nIndents = n;
2666 mpData->pIndents = new RulerIndent[n];
2668 else
2670 sal_uInt16 i = n;
2671 const RulerIndent* pAry1 = mpData->pIndents;
2672 const RulerIndent* pAry2 = pIndentAry;
2673 while ( i )
2675 if ( (pAry1->nPos != pAry2->nPos) ||
2676 (pAry1->nStyle != pAry2->nStyle) )
2677 break;
2678 pAry1++;
2679 pAry2++;
2680 i--;
2682 if ( !i )
2683 return;
2686 memcpy( mpData->pIndents, pIndentAry, n*sizeof( RulerIndent ) );
2689 ImplUpdate();
2692 // -----------------------------------------------------------------------
2694 void Ruler::SetTabs( sal_uInt16 n, const RulerTab* pTabAry )
2696 if ( !n || !pTabAry )
2698 if ( !mpData->pTabs )
2699 return;
2700 delete[] mpData->pTabs;
2701 mpData->nTabs = 0;
2702 mpData->pTabs = NULL;
2704 else
2706 if ( mpData->nTabs != n )
2708 delete[] mpData->pTabs;
2709 mpData->nTabs = n;
2710 mpData->pTabs = new RulerTab[n];
2712 else
2714 sal_uInt16 i = n;
2715 const RulerTab* pAry1 = mpData->pTabs;
2716 const RulerTab* pAry2 = pTabAry;
2717 while ( i )
2719 if ( (pAry1->nPos != pAry2->nPos) ||
2720 (pAry1->nStyle != pAry2->nStyle) )
2721 break;
2722 pAry1++;
2723 pAry2++;
2724 i--;
2726 if ( !i )
2727 return;
2730 memcpy( mpData->pTabs, pTabAry, n*sizeof( RulerTab ) );
2733 ImplUpdate();
2736 // -----------------------------------------------------------------------
2738 void Ruler::SetStyle( WinBits nStyle )
2740 if ( mnWinStyle != nStyle )
2742 mnWinStyle = nStyle;
2743 ImplInitExtraField( sal_True );
2747 // -----------------------------------------------------------------------
2749 void Ruler::DrawTab( OutputDevice* pDevice, const Point& rPos, sal_uInt16 nStyle )
2751 /*const StyleSettings& rStyleSettings =*/ pDevice->GetSettings().GetStyleSettings();
2752 Point aPos( rPos );
2753 sal_uInt16 nTabStyle = nStyle & (RULER_TAB_STYLE | RULER_TAB_RTL);
2755 pDevice->Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
2756 pDevice->SetLineColor();
2757 pDevice->SetFillColor( pDevice->GetSettings().GetStyleSettings().GetShadowColor() );
2758 ImplCenterTabPos( aPos, nTabStyle );
2759 ImplDrawRulerTab( pDevice, aPos, nTabStyle, nStyle );
2760 pDevice->Pop();
2763 void Ruler::SetTextRTL(sal_Bool bRTL)
2765 if(mpData->bTextRTL != bRTL)
2767 mpData->bTextRTL = bRTL;
2768 if ( IsReallyVisible() && IsUpdateMode() )
2769 ImplInitExtraField( sal_True );
2773 long Ruler::GetPageOffset() const { return mpData->nPageOff; }
2774 long Ruler::GetPageWidth() const { return mpData->nPageWidth; }
2775 long Ruler::GetNullOffset() const { return mpData->nNullOff; }
2776 long Ruler::GetMargin1() const { return mpData->nMargin1; }
2777 long Ruler::GetMargin2() const { return mpData->nMargin2; }
2778 long Ruler::GetRulerVirHeight() const { return mnVirHeight; }
2780 void Ruler::DrawTicks()
2782 mbFormat = sal_True;
2783 ImplDraw();
2786 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */