1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511
|
/*
* DockBoundary.java
* 2004-01-02
*/
package org.tigris.toolbar.layouts;
import java.awt.*;
import javax.swing.*;
import java.util.*;
/**
* Abstract Rectangle class for representing the bounds of the docked
* toolbars at a given edge.
* @author Christopher Bach
*/
public abstract class DockBoundary extends Rectangle
{
private ArrayList ourToolBars = new ArrayList();
private Rectangle ourDockableBoundary = null;
private int ourDockableMargin = 10;
private int ourDockEdge = DockLayout.NORTH;
private int ourOrientation = DockLayout.HORIZONTAL;
private int ourSpacing = 0;
/**
* Creates a DockBoundary for the specified edge.
*/
public DockBoundary(int edge)
{
super(0, 0, 0, 0);
ourDockEdge = edge;
ourDockableBoundary = new Rectangle(0, 0, ourDockableMargin, ourDockableMargin);
if (edge == DockLayout.NORTH || edge == DockLayout.SOUTH)
{
ourOrientation = DockLayout.HORIZONTAL;
}
else ourOrientation = DockLayout.VERTICAL;
}
/**
* Creates a DockBoundary for the specified edge
* with the specified spacing.
*/
public DockBoundary(int edge, int spacing)
{
this(edge);
setSpacing(spacing);
}
/**
* Sets the spacing between toolbars added to this edge.
*/
public void setSpacing(int spacing)
{
if (spacing >= 0) ourSpacing = spacing;
else ourSpacing = 0;
}
/**
* Gets the spacing between toolbars added to this edge.
*/
public int getSpacing()
{
return ourSpacing;
}
/**
* Gets the orientation of this edge.
*/
public int getOrientation()
{
return ourOrientation;
}
/**
* Gets the edge that this boundary represents.
*/
public int getEdge()
{
return ourDockEdge;
}
/**
* Determines if the provided point is within the
* dockable range for this edge.
*/
public boolean isDockablePoint(Point p)
{
return ourDockableBoundary.contains(p);
}
/**
* Determines if a drag operation on the provided toolbar
* at the provided point may begin or continue. The toolbar handler
* calls this method when a drag event occurs on the toolbar
* prior to displaying or positioning the dynamic dragging window.
* Subclasses may override this method to return false in order to
* internally process the drag gesture without the ToolBarHandler
* having to undock and redock the toolbar.
*/
public boolean isDraggablePoint(Point p, JToolBar toolbar)
{
return true;
}
/**
* Subclass implementations should return the index at which
* the toolbar should be added when dropped at this point.
*/
public abstract int getDockIndex(Point p);
/**
* Subclass implementation should return the index at which
* the specified toolbar is located within this boundary, or
* -1 if the toolbar is not present.
*/
public abstract int getDockIndex(JToolBar toolbar);
/**
* Subclass implementations should return the row index at which
* the toolbar should be added when dropped at this point.
*/
public abstract int getRowIndex(Point p);
/**
* Subclass implementation should return the row index at which
* the specified toolbar is located within this boundary, or
* -1 if the toolbar is not present.
*/
public abstract int getRowIndex(JToolBar toolbar);
/**
* Sets the location and length of this boundary, and calculates
* the bounds based on validating the toolbar layout.
*/
public void setPosition(int newX, int newY, int length)
{
super.setLocation(newX, newY);
if (ourOrientation == DockLayout.HORIZONTAL) width = length;
else height = length;
setDepth(0);
validate();
// Since the positions of the South and East dock boundaries are
// given as the bottom and right edges of the container, we need
// to shift their bounds back into the container...
if (ourDockEdge == DockLayout.SOUTH)
{
// Make sure the subclass provides a positive depth...
int depth = Math.abs(height);
setBounds(newX, newY - depth, width, depth);
}
else if (ourDockEdge == DockLayout.EAST)
{
// Make sure the subclass provides a positive depth...
int depth = Math.abs(width);
setBounds(newX - depth, newY, depth, height);
}
validateDockableBoundary();
}
/**
* Lays out the toolbars associated with this boundary and calculates
* the depth of the boundary based on the toolbar layout.
* Subclass implementations should lay out the associated toolbars
* and determine the depth of this boundary. At the start of this
* mehtod, the depth of this boundary should be assumed to be 0 and
* should be determined by the time the validation completes, finishing
* with a call to setDepth(). This method usually will not be called
* directly. Instead, a call to setPosition() will call this method
* and will also subsequently verify the bounds of this boundary based
* on the new depth.
*/
public abstract void validate();
/**
* Validates this boundary and recalculates its dockable range.
*/
public void revalidate()
{
validate();
validateDockableBoundary();
}
/**
* Returns the height or width of this boundary depending on
* orientation as determined by a previous call to validate.
*/
public int getDepth()
{
if (ourOrientation == DockLayout.HORIZONTAL) return height;
else return width;
}
/**
* Sets the height or width of this boundary depending on orientation.
* This method should be called by the subclass implementation's validate
* method prior to returning.
*/
protected void setDepth(int depth)
{
if (ourOrientation == DockLayout.HORIZONTAL) height = Math.abs(depth);
else width = Math.abs(depth);
}
/**
* Inserts the specified toolbar into this boundary at the
* provided indices.
* Subclasses generally should not override this method,
* but may provide more detailed behavior by overriding
* the toolBarAdded() callback method instead.
*/
public void addToolBar(JToolBar toolbar, int rowIndex, int index)
{
toolbar.setOrientation(ourOrientation);
ourToolBars.add(toolbar);
toolBarAdded(toolbar, rowIndex, index);
}
/**
* Adds the specified toolbar to this boundary calculating the
* insertion index based on the provided drop point.
* Subclasses generally should not override this method,
* but may provide more detailed behavior by overriding
* the toolBarAdded() callback method instead.
*/
public void addToolBar(JToolBar toolbar, Point dropPoint)
{
addToolBar(toolbar, getRowIndex(dropPoint), getDockIndex(dropPoint));
}
/**
* Callback method called when a toolbar is added to the boundary
* in order to allow subclasses to provide additional handling.
*/
protected void toolBarAdded(JToolBar toolbar, int rowIndex, int index)
{
}
/**
* Removes the specified toolbar from this boundary.
* Subclasses generally should not override this method,
* but may provide more detailed behavior by overriding
* the toolBarRemoved() callback method instead.
*/
public void removeToolBar(JToolBar toolbar)
{
ourToolBars.remove(toolbar);
toolBarRemoved(toolbar);
}
/**
* Removes the specified component from this boundary as long as
* the runtime type of the component is a JToolBar.
* Subclasses generally should not override this method,
* but may provide more detailed behavior by overriding
* the toolBarRemoved() callback method instead.
*/
public void removeComponent(Component component)
{
if (component instanceof JToolBar)
removeToolBar((JToolBar)component);
}
/**
* Callback method called when a toolbar is removed from the boundary
* in order to allow the subclass to provide additional handling.
*/
protected void toolBarRemoved(JToolBar toolbar)
{
}
/**
* Gets an array of the toolbars registered with this boundary.
*/
public JToolBar[] getToolBars()
{
JToolBar[] bars = new JToolBar[ourToolBars.size()];
bars = (JToolBar[])ourToolBars.toArray(bars);
return bars;
}
/**
* Returns a boolean indicating whether or not this boundary
* contains the provided toolbar.
*/
public boolean containsToolBar(JToolBar toolbar)
{
return ourToolBars.contains(toolbar);
}
// Package access only...
/**
* Coordinates the actaul location of each toolbar (edge and indicies)
* with the toolbar's handler.
*/
void refreshHandlers()
{
String key = ToolBarHandler.TOOL_BAR_HANDLER_KEY;
for (int i=0; i < ourToolBars.size(); i++)
{
JToolBar toolbar = (JToolBar)ourToolBars.get(i);
Object prop = toolbar.getClientProperty(key);
ToolBarHandler handler = (ToolBarHandler)prop;
if (handler != null)
{
handler.setDockEdge(getEdge());
handler.setDockIndex(getDockIndex(toolbar));
handler.setRowIndex(getRowIndex(toolbar));
}
}
}
/**
* Returns the "length" (width or height) of the provided toolbar
* depending on this boundary's orientation.
*/
protected int getPreferredToolBarLength(JToolBar toolbar)
{
Dimension d = toolbar.getPreferredSize();
if (ourOrientation == DockLayout.HORIZONTAL) return d.width;
else return d.height;
}
/**
* Returns the "depth" (height or width) of the provided toolbar depending
* on this boundary's orientation.
*/
protected int getPreferredToolBarDepth(JToolBar toolbar)
{
Dimension d = toolbar.getPreferredSize();
if (ourOrientation == DockLayout.HORIZONTAL) return d.height;
else return d.width;
}
/**
* Reflects the provided rectangle about a line passing through
* the point at the provided offset distance depending on the
* orientation of this boundary. This method may be used by
* subclasses (especially at the south and east edges) to lay
* out the toolbars relative to the boundary origin and then
* reflect them about the offset line to produce a reverse wrap
* of the toolbars.
*/
protected void mirrorBounds(Rectangle r, int mirrorOffset)
{
int distanceFromMirror = 0;
if (getOrientation() == DockLayout.HORIZONTAL)
{
// mirrorOffset represents the x-axis
distanceFromMirror = r.y - mirrorOffset;
int newY = r.y - (2 * distanceFromMirror) - r.height;
r.y = newY;
}
else
{
// mirrorOffset represents the y-axis
distanceFromMirror = r.x - mirrorOffset;
int newX = r.x - (2 * distanceFromMirror) - r.width;
r.x = newX;
}
}
/**
* Calculates the bounds of the dockable range based on the
* current bounds of this boundary.
*/
private void validateDockableBoundary()
{
ourDockableBoundary.setBounds(this);
if (ourOrientation == DockLayout.HORIZONTAL)
ourDockableBoundary.height += ourDockableMargin;
else ourDockableBoundary.width += ourDockableMargin;
if (ourDockEdge == DockLayout.SOUTH)
ourDockableBoundary.y -= ourDockableMargin;
else if (ourDockEdge == DockLayout.EAST)
ourDockableBoundary.x -= ourDockableMargin;
}
}
|