moved kdeaccessibility kdeaddons kdeadmin kdeartwork kdebindings kdeedu kdegames...
[kdeedu.git] / kstars / kstars / infoboxes.cpp
blob4671d8e9d674d9d6958beaa8874293d2419078c9
1 /***************************************************************************
2 infoboxes.cpp - description
3 -------------------
4 begin : Wed Jun 5 2002
5 copyright : (C) 2002 by Jason Harris
6 email : jharris@30doradus.org
7 ***************************************************************************/
9 /***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
18 #include <kglobal.h>
19 #include <kdebug.h>
20 //#include <qpen.h>
21 #include <qpainter.h>
23 #include "infoboxes.h"
24 #include "kstarsdatetime.h"
25 #include "dms.h"
26 #include "geolocation.h"
27 #include "skypoint.h"
29 InfoBoxes::InfoBoxes( int w, int h, QPoint tp, bool tshade,
30 QPoint gp, bool gshade, QPoint fp, bool fshade,
31 QColor colorText, QColor colorGrab, QColor colorBG ) :
32 boxColor(colorText), grabColor(colorGrab), bgColor(colorBG),
33 GeoBox(0), FocusBox(0), TimeBox(0)
36 int tx = tp.x();
37 int ty = tp.y();
38 int gx = gp.x();
39 int gy = gp.y();
40 int fx = fp.x();
41 int fy = fp.y();
43 GrabbedBox = 0;
44 GrabPos = QPoint( 0, 0 );
45 Visible = true;
47 Width = w;
48 Height = h;
50 //Create infoboxes
51 GeoBox = new InfoBox( gx, gy, gshade, "", "" );
52 TimeBox = new InfoBox( tx, ty, tshade, "", "", "" );
53 FocusBox = new InfoBox( fx, fy, fshade, "", "", "" );
55 fixCollisions( TimeBox );
56 fixCollisions( FocusBox );
58 resize( w, h );
61 InfoBoxes::InfoBoxes( int w, int h, int tx, int ty, bool tshade,
62 int gx, int gy, bool gshade, int fx, int fy, bool fshade,
63 QColor colorText, QColor colorGrab, QColor colorBG ) :
64 boxColor(colorText), grabColor(colorGrab), bgColor(colorBG) {
66 GrabbedBox = 0;
67 GrabPos = QPoint( 0, 0 );
68 Visible = true;
70 Width = w;
71 Height = h;
73 //Create infoboxes
74 GeoBox = new InfoBox( gx, gy, gshade, "", "" );
75 TimeBox = new InfoBox( tx, ty, tshade, "", "", "" );
76 FocusBox = new InfoBox( fx, fy, fshade, "", "", "" );
78 fixCollisions( TimeBox );
79 fixCollisions( FocusBox );
81 resize( w, h );
84 InfoBoxes::~InfoBoxes(){
85 delete FocusBox;
86 delete TimeBox;
87 delete GeoBox;
90 void InfoBoxes::resize( int w, int h ) {
91 Width = w;
92 Height = h;
93 checkBorders(false);
96 void InfoBoxes::drawBoxes( QPainter &p, QColor FGColor, QColor grabColor,
97 QColor BGColor, unsigned int BGMode ) {
98 if ( isVisible() ) {
99 if ( GeoBox->isVisible() ) {
100 p.setPen( QPen( FGColor ) );
101 if ( GrabbedBox == 1 ) {
102 p.setPen( QPen( grabColor ) );
103 p.drawRect( GeoBox->x(), GeoBox->y(), GeoBox->width(), GeoBox->height() );
105 GeoBox->draw( p, BGColor, BGMode );
108 if ( TimeBox->isVisible() ) {
109 p.setPen( QPen( FGColor ) );
110 if ( GrabbedBox == 2 ) {
111 p.setPen( QPen( grabColor ) );
112 p.drawRect( TimeBox->x(), TimeBox->y(), TimeBox->width(), TimeBox->height() );
114 TimeBox->draw( p, BGColor, BGMode );
117 if ( FocusBox->isVisible() ) {
118 p.setPen( QPen( FGColor ) );
119 if ( GrabbedBox == 3 ) {
120 p.setPen( QPen( grabColor ) );
121 p.drawRect( FocusBox->x(), FocusBox->y(), FocusBox->width(), FocusBox->height() );
123 FocusBox->draw( p, BGColor, BGMode );
128 bool InfoBoxes::grabBox( QMouseEvent *e ) {
129 if ( GeoBox->rect().contains( e->pos() ) ) {
130 GrabbedBox = 1;
131 GrabPos.setX( e->x() - GeoBox->x() );
132 GrabPos.setY( e->y() - GeoBox->y() );
133 return true;
134 } else if ( TimeBox->rect().contains( e->pos() ) ) {
135 GrabbedBox = 2;
136 GrabPos.setX( e->x() - TimeBox->x() );
137 GrabPos.setY( e->y() - TimeBox->y() );
138 return true;
139 } else if ( FocusBox->rect().contains( e->pos() ) ) {
140 GrabbedBox = 3;
141 GrabPos.setX( e->x() - FocusBox->x() );
142 GrabPos.setY( e->y() - FocusBox->y() );
143 return true;
144 } else {
145 GrabbedBox = 0; //this is probably redundant, because mouseRelease should call unGrabBox()...
146 return false;
150 bool InfoBoxes::unGrabBox( void ) {
151 if ( GrabbedBox ) {
152 GrabbedBox = 0;
153 checkBorders();
154 return true;
155 } else {
156 return false;
160 bool InfoBoxes::dragBox( QMouseEvent *e ) {
161 switch( GrabbedBox ) {
162 case 1: //GeoBox
163 GeoBox->move( e->x() - GrabPos.x(), e->y() - GrabPos.y() );
164 fixCollisions( GeoBox );
165 return true;
166 break;
167 case 2: //TimeBox
168 TimeBox->move( e->x() - GrabPos.x(), e->y() - GrabPos.y() );
169 fixCollisions( TimeBox );
170 return true;
171 break;
172 case 3: //FocusBox
173 FocusBox->move( e->x() - GrabPos.x(), e->y() - GrabPos.y() );
174 fixCollisions( FocusBox );
175 return true;
176 break;
177 default: //no box is grabbed; return false
178 return false;
182 bool InfoBoxes::shadeBox( QMouseEvent *e ) {
183 if ( GeoBox->rect().contains( e->pos() ) ) {
184 GeoBox->toggleShade();
185 if ( GeoBox->rect().bottom() > height() ) GeoBox->move( GeoBox->x(), height() - GeoBox->height() );
186 if ( GeoBox->rect().right() > width() ) GeoBox->move( width() - GeoBox->width(), GeoBox->y() );
187 if ( GeoBox->anchorBottom() ) GeoBox->move( GeoBox->x(), height() - GeoBox->height() );
188 if ( GeoBox->anchorRight() ) GeoBox->move( width() - GeoBox->width(), GeoBox->y() );
189 fixCollisions( TimeBox );
190 fixCollisions( FocusBox );
191 return true;
192 } else if ( TimeBox->rect().contains( e->pos() ) ) {
193 TimeBox->toggleShade();
194 if ( TimeBox->rect().bottom() > height() ) TimeBox->move( TimeBox->x(), height() - TimeBox->height() );
195 if ( TimeBox->rect().right() > width() ) TimeBox->move( width() - TimeBox->width(), TimeBox->y() );
196 if ( TimeBox->anchorBottom() ) TimeBox->move( TimeBox->x(), height() - TimeBox->height() );
197 if ( TimeBox->anchorRight() ) TimeBox->move( width() - TimeBox->width(), TimeBox->y() );
198 fixCollisions( GeoBox );
199 fixCollisions( FocusBox );
200 return true;
201 } else if ( FocusBox->rect().contains( e->pos() ) ) {
202 FocusBox->toggleShade();
203 if ( FocusBox->rect().bottom() > height() ) FocusBox->move( FocusBox->x(), height() - FocusBox->height() );
204 if ( FocusBox->rect().right() > width() ) FocusBox->move( width() - FocusBox->width(), FocusBox->y() );
205 if ( FocusBox->anchorBottom() ) FocusBox->move( FocusBox->x(), height() - FocusBox->height() );
206 if ( FocusBox->anchorRight() ) FocusBox->move( width() - FocusBox->width(), FocusBox->y() );
207 fixCollisions( TimeBox );
208 fixCollisions( GeoBox );
209 return true;
211 return false;
214 bool InfoBoxes::fixCollisions( InfoBox *target ) {
215 int dLeft(0), dRight(0), dUp(0), dDown(0);
216 QRect area = QRect( 0, 0, Width, Height );
217 QRect t = target->rect();
218 QRect Box1, Box2;
220 //Set Box1 and Box2 to the rects of the other two InfoBoxes, unless
221 //they are not visible (if so, set a null QRect)
222 if ( target == GeoBox ) {
223 if ( FocusBox->isVisible() ) Box1 = FocusBox->rect();
224 else Box1 = QRect(0,0,0,0);
226 if ( TimeBox->isVisible() ) Box2 = TimeBox->rect();
227 else Box2 = QRect(0,0,0,0);
229 } else if ( target == FocusBox ) {
230 if ( GeoBox->isVisible() ) Box1 = GeoBox->rect();
231 else Box1 = QRect(0,0,0,0);
233 if ( TimeBox->isVisible() ) Box2 = TimeBox->rect();
234 else Box2 = QRect(0,0,0,0);
236 } else if ( target == TimeBox ) {
237 if ( FocusBox->isVisible() ) Box1 = FocusBox->rect();
238 else Box1 = QRect(0,0,0,0);
240 if ( GeoBox->isVisible() ) Box2 = GeoBox->rect();
241 else Box2 = QRect(0,0,0,0);
243 } else { return false; } //none of the Boxes match target!
245 //Shrink Box1 and Box2 by one pixel in each direction. This will make the
246 //Edges of adjacent boxes line up more nicely.
247 if ( Box1.width() ) Box1.setCoords( Box1.left()+1, Box1.top()+1, Box1.right()-1, Box1.bottom()-1 );
248 if ( Box2.width() ) Box2.setCoords( Box2.left()+1, Box2.top()+1, Box2.right()-1, Box2.bottom()-1 );
250 //First, make sure target box is within area rect.
251 if ( ! area.contains( t ) ) {
252 /* if ( t.x() < area.x() ) target->move( area.x(), t.y() );
253 if ( t.y() < area.y() ) target->move( t.x(), area.y() );
254 if ( t.right() > area.right() ){ target->move( area.right() - t.width(), t.y() ); }
255 if ( t.bottom() > area.bottom() ) target->move( t.x(), area.bottom() - t.height() );*/
257 int x = t.x(), y = t.y();
259 if ( t.x() < area.x() ) x = area.x();
260 if ( t.y() < area.y() ) y = area.y();
261 if ( t.right() > area.right() ) x = area.right() - t.width();
262 if ( t.bottom() > area.bottom() ) y = area.bottom() - t.height();
263 target->move(x,y);
265 //Reset t
266 t = target->rect();
269 QRect upRect = t;
270 QRect downRect = t;
271 QRect leftRect = t;
272 QRect rightRect = t;
274 //Fix collisions
275 if ( t.intersects( Box1 ) || t.intersects( Box2 ) ) {
276 //move t to the left one pixel at a time until there is no
277 //intersection with Box1 or Box2.
278 while ( leftRect.intersects( Box1 ) || leftRect.intersects( Box2 ) ) {
279 ++dLeft;
280 leftRect.moveTopLeft( QPoint( t.x() - dLeft, t.y() ) );
282 //If leftRect is outside area, set dLeft to a nonsense large value
283 if ( !area.contains( leftRect ) ) { dLeft = 100000; }
284 //repeat for right, up and down directions.
285 while ( rightRect.intersects( Box1 ) || rightRect.intersects( Box2 ) ) {
286 ++dRight;
287 rightRect.moveTopLeft( QPoint( t.x() + dRight, t.y() ) );
289 if ( !area.contains( rightRect ) ) { dRight = 100000; }
291 while ( upRect.intersects( Box1 ) || upRect.intersects( Box2 ) ) {
292 ++dUp;
293 upRect.moveTopLeft( QPoint( t.x(), t.y() - dUp ) );
295 if ( !area.contains( upRect ) ) { dUp = 100000; }
297 while ( downRect.intersects( Box1 ) || downRect.intersects( Box2 ) ) {
298 ++dDown;
299 downRect.moveTopLeft( QPoint( t.x(), t.y() + dDown ) );
301 if ( !area.contains( downRect ) ) { dDown = 100000; }
304 //find the smallest displacement, and move the target box there.
305 //if the smallest displacement is 100000, then the function has failed
306 //to find any legal position; return false.
307 int dmin = dLeft;
308 if ( dRight < dmin ) dmin = dRight;
309 if ( dDown < dmin ) dmin = dDown;
310 if ( dUp < dmin ) dmin = dUp;
312 if ( dmin == 100000 ) { return false; }
313 else if ( dmin == dLeft ) {
314 target->move( leftRect.x(), leftRect.y() );
315 } else if ( dmin == dRight ) {
316 target->move( rightRect.x(), rightRect.y() );
317 } else if ( dmin == dUp ) {
318 target->move( upRect.x(), upRect.y() );
319 } else if ( dmin == dDown ) {
320 target->move( downRect.x(), downRect.y() );
323 else // no intersection with other boxes
324 return true;
326 //Set Anchor flags based on new position
327 if ( target->rect().right() >= width()-2 ) target->setAnchorRight( true );
328 else target->setAnchorRight( false );
329 if ( target->rect().bottom() >= height()-2 ) target->setAnchorBottom(true);
330 else target->setAnchorBottom(false);
332 //Final check to see if we're still inside area (we may not be if target
333 //is bigger than area)
334 if ( area.contains( target->rect() ) ) return true;
335 else return false;
338 bool InfoBoxes::timeChanged( const KStarsDateTime &ut, const KStarsDateTime &lt, dms *lst ) {
339 QString ot1 = TimeBox->text1();
340 QString ot2 = TimeBox->text2();
341 QString ot3 = TimeBox->text3();
343 TimeBox->setText1( i18n( "Local Time", "LT: " ) + lt.time().toString()
344 + " " + lt.date().toString( "%d %b %Y" ) );
345 TimeBox->setText2( i18n( "Universal Time", "UT: " ) + ut.time().toString()
346 + " " + ut.date().toString( "%d %b %Y" ) );
348 QString STString;
349 STString = STString.sprintf( "%02d:%02d:%02d ", lst->hour(), lst->minute(), lst->second() );
351 //Don't use KLocale::formatNumber() for Julian Day because we don't want
352 //thousands-place separators
353 QString JDString = QString::number( ut.djd(), 'f', 2 );
354 JDString.replace( ".", KGlobal::locale()->decimalSymbol() );
356 TimeBox->setText3( i18n( "Sidereal Time", "ST: " ) + STString +
357 i18n( "Julian Day", "JD: " ) + JDString );
359 if ( ot1 == TimeBox->text1() && ot2 == TimeBox->text2() &&
360 ot3 == TimeBox->text3() )
361 return false;
362 else {
363 checkBorders();
364 return true;
368 bool InfoBoxes::geoChanged(const GeoLocation *geo) {
369 QString ot1 = GeoBox->text1();
370 QString ot2 = GeoBox->text2();
372 QString name = geo->translatedName() + ", ";
373 if ( ! geo->province().isEmpty() ) name += geo->translatedProvince() + ", ";
374 name += geo->translatedCountry();
375 GeoBox->setText1( name );
377 GeoBox->setText2( i18n( "Longitude", "Long:" ) + " " +
378 KGlobal::locale()->formatNumber( geo->lng()->Degrees(),3) + " " +
379 i18n( "Latitude", "Lat:" ) + " " +
380 KGlobal::locale()->formatNumber( geo->lat()->Degrees(),3) );
382 if ( ot1 == GeoBox->text1() && ot2 == GeoBox->text2() )
383 return false;
384 else {
385 checkBorders();
386 return true;
390 bool InfoBoxes::focusObjChanged( const QString &n ) {
391 QString ot1 = FocusBox->text1();
393 FocusBox->setText1( i18n( "Focused on: " ) + n );
394 if ( ot1 == FocusBox->text1() ) return false;
395 else {
396 checkBorders();
397 return true;
401 bool InfoBoxes::focusCoordChanged(const SkyPoint *p) {
402 QString ot2 = FocusBox->text2();
403 QString ot3 = FocusBox->text3();
405 FocusBox->setText2( i18n( "Right Ascension", "RA" ) + ": " + p->ra()->toHMSString() +
406 " " + i18n( "Declination", "Dec" ) + ": " + p->dec()->toDMSString(true) );
407 FocusBox->setText3( i18n( "Azimuth", "Az" ) + ": " + p->az()->toDMSString(true) +
408 " " + i18n( "Altitude", "Alt" ) + ": " + p->alt()->toDMSString(true) );
410 if ( ot2 == FocusBox->text2() && ot3 == FocusBox->text3() )
411 return false;
412 else {
413 checkBorders();
414 return true;
418 void InfoBoxes::checkBorders(bool resetToDefault) {
419 if (resetToDefault) {
420 TimeBox->setAnchorFlag( InfoBox::AnchorNone );
421 GeoBox->setAnchorFlag( InfoBox::AnchorNone );
422 FocusBox->setAnchorFlag( InfoBox::AnchorNone );
425 if ( GeoBox->rect().right() >= Width-2 ) GeoBox->setAnchorRight( true );
426 if ( TimeBox->rect().right() >= Width-2 ) TimeBox->setAnchorRight( true );
427 if ( FocusBox->rect().right() >= Width-2 ) FocusBox->setAnchorRight( true );
428 if ( GeoBox->rect().bottom() >= Height-2 ) GeoBox->setAnchorBottom( true );
429 if ( TimeBox->rect().bottom() >= Height-2 ) TimeBox->setAnchorBottom( true );
430 if ( FocusBox->rect().bottom() >= Height-2 ) FocusBox->setAnchorBottom( true );
432 if ( GeoBox->anchorRight() ) GeoBox->move( Width, GeoBox->y() );
433 if ( TimeBox->anchorRight() ) TimeBox->move( Width, TimeBox->y() );
434 if ( FocusBox->anchorRight() ) FocusBox->move( Width, FocusBox->y() );
435 if ( GeoBox->anchorBottom() ) GeoBox->move( GeoBox->x(), Height );
436 if ( TimeBox->anchorBottom() ) TimeBox->move( TimeBox->x(), Height );
437 if ( FocusBox->anchorBottom() ) FocusBox->move( FocusBox->x(), Height );
440 #include "infoboxes.moc"