vldocking_2.1.4/0000755000175000017500000000000010573516352013525 5ustar twernertwernervldocking_2.1.4/jar/0000755000175000017500000000000010614736505014301 5ustar twernertwernervldocking_2.1.4/src/0000755000175000017500000000000010573516344014315 5ustar twernertwernervldocking_2.1.4/src/com/0000755000175000017500000000000010573516344015073 5ustar twernertwernervldocking_2.1.4/src/com/vlsolutions/0000755000175000017500000000000010573516344017474 5ustar twernertwernervldocking_2.1.4/src/com/vlsolutions/swing/0000755000175000017500000000000010573516344020623 5ustar twernertwernervldocking_2.1.4/src/com/vlsolutions/swing/docking/0000755000175000017500000000000010573516350022236 5ustar twernertwernervldocking_2.1.4/src/com/vlsolutions/swing/docking/animation/0000755000175000017500000000000010573516350024215 5ustar twernertwernervldocking_2.1.4/src/com/vlsolutions/swing/docking/animation/AnimationEvent.java0000644000175000017500000001241310573516350030002 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking.animation; import java.awt.*; /** An Event describing the state of an animation * * @see AnimationListener * @see ComponentAnimator * * @author Lilian Chamontin, vlsolutions. * @version 1.0 * */ public class AnimationEvent { /** state identifying the beginning of an animation */ public static final int ANIMATION_START = 0; /** state identifying a change in the animation (the component has changed of bounds) */ public static final int ANIMATION_FRAME = 1; /** state identifying the end of an animation */ public static final int ANIMATION_END = 2; private Component source; private int state; /** Event Constructor. * @param source the animated component * @param state the state of animation (ANIMATION_START , ANIMATION_FRAME or ANIMATION_END) * */ public AnimationEvent(Component source, int state) { this.source = source; this.state = state; } /** returns the state of the animation (ANIMATION_START, ANIMATION_FRAME or ANIMATION_END) */ public int getState(){ return state; } /** returns the source of animation */ public Object getSource(){ return source; } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/animation/AnimationListener.java0000644000175000017500000001135610573516350030513 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking.animation; /** The AnimationListener interface is used to notify listeners about the state * of an animation process (animation start and end). *

* This interface is used by ComponentAnimator, generally to block * events management during animation phase. * * @see ComponentAnimator * @see AnimationEvent * * @author Lilian Chamontin, vlsolutions. * @version 1.0 * */ public interface AnimationListener { /** This method is invoked when the animation state change. *

Changes are relative to animation start, sequence(frame) and end. * */ public void animation(AnimationEvent e); } vldocking_2.1.4/src/com/vlsolutions/swing/docking/animation/ComponentAnimator.java0000644000175000017500000002517710573516350030531 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking.animation; import java.awt.*; import javax.swing.*; import java.awt.event.*; import java.util.ArrayList; /** Utility class used to perform move/resize animation for awt/swing components. *

* This class moves/resizes a Component given a start and end Rectangle and * a duration. *

* Movements and listeners notifications are processed in the Swing Event Thread. * * @author Lilian Chamontin, vlsolutions. * @version 1.0 * */ public class ComponentAnimator { /** The animated component */ protected Component comp; /** the component's start bounds */ protected Rectangle startBounds; /** the component's end bounds */ protected Rectangle endBounds; /** the animation duration in seconds */ protected float duration; /** animation start time System.currentTimeMillis() */ private long start; /** time elapsed since the beginnig of animation */ protected float elapsed = 0; private Timer timer; private ArrayList listeners = new ArrayList(3); /** Single-shot animator (use another ComponentAnimator for a new animation). * * * @param comp the component to animate * @param startBounds initial bounds of the component * @param endBounds end bounds of the component * @param duration duration of animation, expressed in seconds * @param listener single listener used for animation notification */ public ComponentAnimator(Component comp, Rectangle startBounds, Rectangle endBounds, float duration, AnimationListener listener) { this.comp = comp; this.startBounds = startBounds; this.endBounds = endBounds; this.duration = duration; addAnimationListener(listener); start(); } /** Reusable component animator. * To start an animation, don't forget to call the {@link #start() start() }method. * */ public ComponentAnimator(Component comp, Rectangle startBounds, Rectangle endBounds, float duration) { this.comp = comp; this.startBounds = startBounds; this.endBounds = endBounds; this.duration = duration; } /** Starts the animation. *

The component is setBoundsed to startBounds and made visible, * than a Swing timer is started to process the animation (refresh rate is 100 ms). *

the ANIMATION_START event is then fired to all listeners. */ public void start(){ if (duration == 0 ){ // heavy weight == no animation fireAnimationEvent(new AnimationEvent(comp, AnimationEvent.ANIMATION_START)); // already the end comp.setBounds(endBounds.x, endBounds.y, endBounds.width, endBounds.height); comp.invalidate(); comp.validate(); comp.repaint(); fireAnimationEvent(new AnimationEvent(comp, AnimationEvent.ANIMATION_END)); } else { comp.setBounds(startBounds.x, startBounds.y, startBounds.width, startBounds.height); comp.validate(); comp.setVisible(true); timer = new Timer(100, new AnimationActionListener()); start = System.currentTimeMillis(); timer.start(); fireAnimationEvent(new AnimationEvent(comp, AnimationEvent.ANIMATION_START)); } } /** Cancels the animation (the component is not reset to its initial location/size) */ public void cancel(){ timer.stop(); } /** Adds a new listener to the animator * @param listener the listener */ public void addAnimationListener(AnimationListener listener) { if (listener != null && ! listeners.contains(listener)){ listeners.add(listener); } } /** loops over the listeners to fire animation event */ private void fireAnimationEvent(AnimationEvent e){ for (int i = 0; i < listeners.size(); i++) { ((AnimationListener) listeners.get(i)).animation(e); } } /** Returns the duration of the animation * * @return the duration of the animation, in seconds */ public float getDuration() { return duration; } /** Sets the duration of the animation. *

Warning : do not change this value during an animation * * @param duration the new duration in seconds */ public void setDuration(float duration) { this.duration = duration; } /** Returns the end bounds of the components. * * @return the end bounds of the components. */ public Rectangle getEndBounds() { return endBounds; } /** Sets the end bounds of the component. *

Warning : do not change end bounds during an animation. * * @param endBounds */ public void setEndBounds(Rectangle endBounds) { this.endBounds = endBounds; } /** Returns the start bounds of the component. * * @return the start bounds of the component (those of when animation starts). */ public Rectangle getStartBounds() { return startBounds; } /** Sets the start bounds of the component for animation. *

Warning :do not change start bounds during an animation * @param startBounds the start bounds of the component. */ public void setStartBounds(Rectangle startBounds) { this.startBounds = startBounds; } /** Inner action listener to hide actionPerformed from the public API. */ private class AnimationActionListener implements ActionListener { public void actionPerformed(ActionEvent e) { long time = System.currentTimeMillis(); elapsed = (time - start) / 1000f; if (elapsed < duration) { float f1 = (duration - elapsed) / duration; float f2 = elapsed / duration; Rectangle newBounds = new Rectangle(); newBounds.x = (int) (startBounds.x * f1 + endBounds.x * f2); newBounds.y = (int) (startBounds.y * f1 + endBounds.y * f2); newBounds.width = (int) (startBounds.width * f1 + endBounds.width * f2); newBounds.height = (int) (startBounds.height * f1 + endBounds.height * f2); comp.setBounds(newBounds.x, newBounds.y, newBounds.width, newBounds.height); comp.validate(); fireAnimationEvent(new AnimationEvent(comp, AnimationEvent.ANIMATION_FRAME)); } else { // the end comp.setBounds(endBounds.x, endBounds.y, endBounds.width, endBounds.height); comp.validate(); timer.stop(); fireAnimationEvent(new AnimationEvent(comp, AnimationEvent.ANIMATION_END)); } } } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/animation/package.html0000644000175000017500000000053510573516344026504 0ustar twernertwerner

Swing Components Animation.

The animation package provides classes and interface requiered in component animations for the docking framework.

There is not much animation for now (only auto-expand / auto-hide features), but this could change in future versions (think about animated docking...). vldocking_2.1.4/src/com/vlsolutions/swing/docking/doc-files/0000755000175000017500000000000010573516344024106 5ustar twernertwernervldocking_2.1.4/src/com/vlsolutions/swing/docking/doc-files/attach16v2rollover.png0000644000175000017500000000051610573516344030266 0ustar twernertwernerPNG  IHDRabKGD pHYs  tIME  TIDATxڝS+0}pj[[Q#~/ܢATW t!Ulg7IR#7{ ?qts+$treyA՘C4*Z/!Q݊H&Rx}OS?uN †144'}0BTI^B94MBB?L|!M"74l/Uk:BIENDB`vldocking_2.1.4/src/com/vlsolutions/swing/docking/doc-files/close16.gif0000644000175000017500000000152010573516344026047 0ustar twernertwernerGIF89a!,-H*\(0@A !q"Æ-RD(qÏCI`@;vldocking_2.1.4/src/com/vlsolutions/swing/docking/doc-files/close16v2rollover.png0000644000175000017500000000041610573516344030126 0ustar twernertwernerPNG  IHDRabKGD pHYs  tIME  IDATxS ͸]---ZR\ydH^я -ZPd/Ĵ. L}9(D!@9-ZTuѺԜ3ۗ5B$t|ء@$[/n3XY7R%aak V IENDB`vldocking_2.1.4/src/com/vlsolutions/swing/docking/doc-files/dock16.gif0000644000175000017500000000152310573516344025665 0ustar twernertwernerGIF89a!,0H*\H0C  -b<Ç 7Vd8ɓ$;vldocking_2.1.4/src/com/vlsolutions/swing/docking/doc-files/dock16v2rollover.png0000644000175000017500000000036510573516344027744 0ustar twernertwernerPNG  IHDRabKGD pHYs  tIME  ,IWMIDATxc@!lN8U NN C?00J,-B 2  XM\4ۇmCj[O\_,s>F.% +PIENDB`vldocking_2.1.4/src/com/vlsolutions/swing/docking/doc-files/docking.gif0000644000175000017500000011274310573516344026223 0ustar twernertwernerGIF89a,QH:D]b^X8pfkcckmJkkkU7skkssk{sksss{{o{{{{k-HR%T1R1kL\Pqsx{{=cOpcs`s+RZmsZk{xxdx{ʵƹενƽ!)59BBBBJJJJJRRRRZZ`hckJRZbXf%iC] s{{y.wF~hb{{ℜy|ߎڭνֽ޽5GN%a.cFoRd{ޥ11J֜Ƶʜ縷軐ƽƥƵֽ樂便Ωƽνννu眽޽ڵ,,teKc*%aC#BD/jǍ;)rɇ'\Ĕ/Yt L4ot'I% I4hQ-^ 0b֯`ÊKٳhӪ]˶۷pʝKݻeÈw/-`(1C!'R(ǐ#KL˘3k̹ϠCMӨ)KY'Ib)"a"NVC^͛o)N|qȋ'?9ˣ;8±k}O~ϫO~wcq䘑bsG\xrI%P#!/7`oO@ѡP($X&',(c4h#:> BIF& dkL6PF)TViVFlee|}`RF8r!R!,`E ?-DtL5RWT؆g|a^|vqGhK!B!®F@``  PƵ]OxCP!Ee1mE;fСpDX́?LX;mcDN:.|+|7<+=}s/oF`6cmơ6r.n0Lj SⴠC z0)L ‚<:P(J@?`@:iH@)ģx p|al88` w4 }lB 6q 8E)HVE*bQ`" E(dL4q`t(2l F;q HA<"A}_[02~dD9 !K J`|"PTa}C6:(n ?& PATX$vG~9*t`_zG [$?@* '~ @JЂM(@iOӡ$JQV(F7Pv}f3, jB> pQOB)0 a ԁJ0ʣ V`m( }FQX L0L*c#ղV Hq>ǵX!L5 p2,@*|f؁E@*Vkֲ.ֱI,cFֱ,d3[VbճVh7KZ͚Ei?Z֮6k!Kͭnwb ^(>51A jB9[ B*C 1!'{ X OL W{, WT O0PJ@ U0~x }/n}oSb1_x7>1sbW>{ "SjOǯt =kTkҵ^ekG v'<8\A6"tKAj D@-Ta +/R`r#u莬˭vlmy;v7ٝos8-pc,˺;~'.33{<Ϭ];rfV%O9)r-9_.3L77g@0] ]@g!6I(GRc]6Wu[c:k]dٿwsn{~</Mw;񐏼'O;]폏z!A8! p/G魑һP=Yշ}g{={~q{+_~w ~}c~w/?ׯˏ{^'' %\pW Xz@{zh `H{(8{{ȁ }8؁'#,.&3()87X ȃ6;(4=hA zEX+HI؄gNFSzUX{GXPhz[ȄITȁL/( X^?4p|Vz|#{zs|{ph{G|Ȃ}7|~x{RzȇPW {U({M(H耧XzȊ`h (*U ( 耻(8z|X芆Ḣzx%H { p8ᨎ0{؎:XXzb(+(SxiFhvz{Ȁx'9yzINXݗ{}}W7|}(~*,i{~#n˨ @y p .`4@(KI +WѨp%G~g(!|g{(\guw|hY8x98ȗz _i Y(GsGAɕv{ z ])^p ^I8Jǐ y'h"89}GIםy蝲ti\XCxgG|Ig icْbYؓ .ЛLJDɕK؎zLɠ/IkIcq}(o{9iqXk{{%x)y >ژ;Ș4wɣ99Jژө#/ȐNLH|QZ#z_/:iҸۘh Y[٠H~)Չ3~Xy بzȅ)ȈȤΗטN8lz|Ǚ~Wjɘco(8Z{ziIٷY($ʫج'vZෞʖYؑI}#I]+IʏIdJ J*jy'ʦIi'(GIJ9i[};}ٙTʨz۹y#wUJ ( kٸ|E؞ZEJ%j誈*zٯ7FГp Z+ ` [; _Y]{ @^k]+`۶\ t۶a a뵳 d`z zc}+k vn{[˸KrKyKPn[ihKd۹n +[bs˶+x\{x˹[| ;˻c+Yk;˵k+oJ;[{ۿ * ٺR#@Kx9 ۋC[ }!tزڇ.9؋W*%K$|.,j<ʫZ״:ZX>x2Ǿ Ҁ :ėY @Xtlʦ+2{ʤةٗ&zX<[֊dliWʳNL޲X7׍ؤ6ZZlBEvmܷuwo࿅'>vTȕ'gyR@EҺmJwŏ'_{5jִ:p̟Ξ=ÆSv,mg@yG}LQᔶf#pB +B 3P -C-Т .H.H  E2b$g,Fs,Ì2 3R d 6`cI&hI7x 9+R:K;>ȼ46#8Yf9YlFo?GxǞ|NYWH58s3@i4[чqjIyx 6vR45x=RFU:-U ^XoGԏ2 X  ",k_C|t5MqiO}JZ<ִ`,^ pDYD#aM5aQlVІ'ѭn[6^h#Ǭ5 \Muᯂeb Ў#@ #m{ ZD&1n&AȞe;2[dtw}A(<QAxW I qtҍ%|cBeLoƑ7Gա=D'RX֢ Sލ5IAJP=MR>}IL33>ipІ&>ɕ_=WjPR #F hAbmB!;bԈ}SQ*Tm#ĕa@#5׫>qmܠU1Ech@ ~e$ kxC48 g#ЬƎ @Cf6*b6KBLf3'E`>2pH'XDIRi}7N׈_7ѩ+Z aDȐcޏzՎy5dMkȪ=yoK0d4<#'U/ث<ѴAEKq54@ `2X&ߡn$"ZYf>܊&Y(Wn{Р X cB]i LCڭhT:r `gI;! C$#٠ YVYь ?ӢZچMJ?Xjv#TEp(N@Ё` 8ۆҵ?91 ! ,ZMM"f:Ǩ~BLd}~!7:/`(xCp0 aŋlCRXc.aQdFY&.e(s&'î0Ӟ̍2- 0/p+Z1R6b1]tzR%* ֖£цt͏pU+[dHÕ[.4>`vmsof/6 Gۛ|Rc%4!_uR{db;c[y3Kz )m{nkr:I%iDɕ),y24XzcZ ̹&z2?j:?* rY3W7Sq3pp(zp0hSkB &k(B㸨KУ Iܡ|~9q;@@ Q2*6Lba^3'3;"[ix_?Xm[-ЍW)u NťLLB-[kRu\ɽQ֫Mԏy9W`Nu4\ޜݝa؝!s!uZbB\YP}Y]mU$^r\y==\\vԎX*~`H}Sdp8?[h>RecR͜<[M1d1lWGΎuC\3.&.(1[H )\p ʭ[NY,*Gj!xzBY ]`T9-.#]]VcM=V]MU>5~ PXA`mS%mc3.\^y3Jug_^zncWeG/UueܮB.(Υ83guI+U6Ssa7v` Q\er = =J'|!aTuU fi`^e3sc=bە]a#V]៍U]ZkW2VqXSO^4@6_z2yr6`ek&}׹ĵZpSeTUl.`~2_ drp'yRDE9@(RFiSlM g/XҍZ'^9Yam"Y -Nb=^aN&~fEe\nuN͍T6+~CFfFEj]XwETЦnǍב&Alh8g@?ޱh3`-ͮUiF`J o@`QN—]^\cj"եn#F> Mq}dT~nTS-jUq O8ڼ+MhfrW qnU($l.ViԵ SWpo6+6^<׶Tfedƚ8THT@tA7AD'DWtB'T0GGJtKFS8C/JHt%)N(VWi+^ul}bm- X,ViEd%'i V P =N][ ۆ.Bf/aC`` v!R`OBYD&. .l V^tuu_PKgwyKwwIowv_txGY@iX= x؃X'x؆/xxwo؄xxxgx7yyfHqVM ntu̮Y^vNОFmWXY~HzzzzzzjZivz{{/{?{LJnP8QxZ%\W%R1纽Z⊅uQk%ύj6=tMPw}@8~qـiV!le!l)  -ؘvږҼhi$n) "&eX#} Xs8i y(**>}qGwܡ |}}VJ)J'ҧ iqI)YDDlm3tSE H@BKuݢ:y3{T{̍b ~ګjvi@.HZxbG L A'E"h p-guYUlpV UXlL2A@BI uDQIPwBˎG":=NC>cn0 @ .Ϭ_Λfe+sr8‚#(hP]"`eNUMV&FqZ98_@uuዯV_}# ڭ58+䘻 N/l|#:0;A)@ whUnTQl^TC7A j81y+j^5 .|hjC1%~SL/SJjEtdpA(wAq\謁9P:ˬ88Qr #H VsPm|00E¬m`-$XBEm,:$㶷ŭ, IZ1DqHuO-AM7t,=VjϔZV2o2 da0V6,~" x0QOk3Ih A9&`B V y,;e>d"Bm]p@T(#71Cږz$o~C)'U &Ԋ@cMe%d>DA"2SX L d>ٝ>jbprT@̇ = zkWêCá8h!KR~>̓J1$ʲ4NTUI0ŸלJ5QɺNb!*M3}ȫԩ!C9L@ħTc;Nj@ՁU{[| \RZMkW"oQ8T fY.`M\+fY r7 d42 hށl~GGV`} ?|U#e>a*Q-mZߑ|R P<]3rX@6΃ox:{c!@.2d#/9N.{!\C( ;֑ucc.lf5g^6ùt)o,^󱏽#C\.?"ו=@mZ8!^ J4}C ͂K 6+:@&P&JR"! |˭E3jtCU#Ȫ=x\ ;_õ65[Rq)5'ei,8Ytq@$…ފ"02j釿~ԣ1|'?_uq>QO"xPNNe pOۀ" _!U 02/"Cb69X7Ƅ1̌􌍻MUb3a{a* jVGܞ(,UCQ#Swo';K0`rtcX>QR0y*M4erXܬAt@5f[>Q@B=ŨcOTթA./ i؇>&%d?oB?U?igƧ=dhO=xh^AyD[xH 5 M!Ez|Z=InxK*e1_>Z[E ^ \4XJaND>8:YM^ppqOiȂR@] e ZC߹3z[!y̟ WJdK$L$MLePC/VzducBBe\0ÂdԜ%RX@bu&r#V#M#N#祢]y-Z[A[>+`R [09歁ϳIZ}O :&1=ec.fƴuݡUY…V:@3R 0}*f#b#bp^0f,*&+'`0eV` s[mO ӳmi x^s^O#v'wƢy}tN'x>q΢|>K`e7tC2d(_m A僟VXRm}R pu.JiB:siDjy(#/]2aG)[VR50АH @>ia*5k[%>u@[T@}^@!.ekt":R[9?Tdޒ꓂!Znԥ,⥶%2kgP`^(2,,a>i:K_(hJ%Tj%\h]Y/US.DNbG4SFg^Ԭlae#ED> s%6&](az!Q<`tF ^,2yFԵ2!aXfE%e`""fO+FT+Egt:@0$lx5:eZ+^nf..i.bv.~螮..:QQvVKHX qrk*-ha">!*4ѱmۖT3lcaX :oڄ>3:Ě"f"of!ӾrҽcέFgQޞB9T+" 1V+.)6l{.ovfʾoed2 cFnZ/H="8^ +ƟveXR}ӮaC kJ$@8`B 11]1&*d2"ڪo1w1*qI1C g.3N0yd11q1. w!;!7@#q"O2>@%[2́1( I'B&8z,,2-rik =@52 0k2pQ&Sr0�"_2#r0;@2'g3}2ܥ &ﲇ#0@'3\3;1qUʮ-Coזc_--@4D5":rV%r)\;;3' pٱ9{('] /7@}0_.G]9@'c4ICr0k4]#@Hʵ5{2NZmd91 ND≞$Ndƀ4uy1S;5TOTWuT_T 0[a ;2zr̅ts4^])44M&171:{2Bk!Iq`&_3B';76*qPTr=1>0p$7@6hϲp52#Yaa5M`7@b8_j`/b2b^6.vN+^FNqj5FN~daw⌆ljxww/L a&w8p{|{;p}ww|7p{w}7}7;07GO8W81eb2$I6LT$seIW$TIeؔcYOiMxwV _hdUr7BwZ,5IR lHExTG4uGMLE@DoXd&s_6 _\pB@99㹛ǹRncO_ ya׆CO؋Dr3Ks+ޭ"{)*1fwOD4z-:خ@zr8=FH+0C7(C2xCrZw;;;;{sO)+;;f&d/?3&& 2ldl7?{)s)[Qw+]l+L^ku1` ljujm@'p&}c&l&>'>?G~O>SW>_[>g~>ȓrO|*y}mD՗%v^*'oby][CG{lpZ4 ``Rm7D 7R H ۽ч#}<< ^bJ9L,!-~o{.j]#r8'AG?|wӇ$8N,="aI< ش)eK6 0&J,ˢD*5ڔMI2*եGVU*جXlX8 @'Ydh\Ǐ^'b` 6|qbŋ DE֬=#IƣGD:">?wsG#GŢ- Xֹ'|Rqw 'Cq^](v׫s߮:ཇ'/xG-. r2.2Yg?‘69f=И8a/١L8 @}DE p".aN9[+zGqH :$qR$:I'jCd#>2<1$K2!0[y 4pz'rp LOo&}dF*I69Rn.}iSSBMRQ,UOSuUQ[r 5ܣC/2X@ Bt G<41Z5k e+?b̐ xx@z|ݗ~({'~gL+N_bҌl.ˬ"ef%eăh  (eHN&V(eH rfZOVȡTfyh hȥ+sN<꬯֚뭯j6{lzZ+чa]gů;am3VHaX`diHr* iG8!̃r'tn=tTƏ?+7mQ|YXQK̿r?̋[8KVaSpi^({:!u h޾|02ߞѿu ]E$?ކ4DbSb&uA&R ,Zw(nuMGVf]~|^zBb.8Ƹ Lbxm8B2ސ17>[X aGFHþY[)1[ 6X20.Fir˹FOyG? YHCrX]>Ѱ#boaq!Y _1hI21Hx䏄$jZ` Ze,i9K[e.yK_f0Kt+`P;t^fpzΆ6?$V"Юh Tg:ٹNwD=;<9x5| ) @AdV =y'q vCOYWZT(-2эvGIҒԤ)EJOR/F;1*^h Y,N!YB>lne">QC%*Rt9e Zp^XZְh5kZٺVm[ZWupE:yuiOsd. ^ i%բ2~4D}~~kVӮvzwޯ\\z-ֺzd$k};ZtԸ2w"FD*A+(5߸qok,Uz`W?>;8ws^}")?uIo6[}Y9˖.7cnQ|4wR{7*A{i;m\C^n&F%rLA;|'yA|9y[ bP eZײ\l/[X}޴{˪ѵ! ]xG%t>hN'"A}3??~󗟈q*5Q"лG9c ӊb%~\ͬJ/j/ pPw O(x(8I A0AJMWPY0OW0[PkmPqa326Bnލ+ z>K ;n n jfdMkƨA??adA+4QފĎ7Q&t?.:tL1qWV1/L3E@(Anq9AbNFFFIGUQg4 `G 5HHH:;3A@K1L2LDҤ@5$6I$0Mw.I`\1'OI- 2bP R R2QРQk\Fw]{HTHSuI4:AF>!>Nu>3TK" #l ^*hab4xl6j@Km*069&V3T8Jj0V-c`fdh֜iZ+dh*PрB!,!\F UjeQuT |tRH/^sISsw@a3K0ВbL plȲMbj̬,&hApclq ̋r f켨n̕mvȖ,0׼rSLh dLښ l .`gsm2[hyUFVI aI@ Qvk5S^e|o;<UaaU[U066%qѤ>M(o-@jrCpwox!mof@hL`Y1x Bf'roV@ \! j\5R{^t:@T;e@<<4`}rTfU0isKXѢm vǀlfxvlƪWRL mq]e wtSƠmsl"mXf ܤw Ei8@O x6Fwj˵`HIQWH{V|`:ϗζ<ն_V>ssnKtDL2EY R.͖ٖHjp9E i+Cǹ&8'ˈ r8`Pyiϵ j ]Q@R)uHw^5ysDu<_TUKM~MӖ,ndaWG^B|nAQvnA,_arf80/ 2\VFwyQ@Uy=;lS=Km?`a 8m Pk Z.K,+ Ѯ$/TX{:7?:;6_T8UY05Ynv @ oFVjjx,luS^:LS o@0ޭ5W0tz*0L-k:k O^ȠT?遞n |e 7\{ \e`d |n`o-\n u@v}C|^d;`O@#H eqߖ,M-2?ֳ,siux s\L*[E#QpazOOEj+3D5N 96|)<\cb9=c+h!' 2YrCo9&]#6̼x"o=!%V&=m oLqM&ї\Ʉo]/0Jg5#_!\!؝./Β]P~ 6rˏ˅e,>NaM4.e-M !ѐ!N) e}k_+8gq=O)3N!z`z{*3+9;5/KC>O^W^=Xܜ"=ڝ#р(axD@x >-ߕl"=sص1Ы~1yנv;#APؾ3~>$3? ?W7y}6xuaQXt-/uq=%Kv}Vp/ثX9 \M1;M@ LtkxO5ghԯjp+Mzݹ[sO>ZPpvW)Ƶpg aFPBX!euYV e.ƚ)cRxj&jY^;>neWow\>XKĄsO:)C Uw . UZ jEUw=erVV}UPe o Ua#tG`j jbH(a*jhqh::t֙A]((' (Cn6@Jk!%rG@4;3obQF ـ5Z{QUyNY XfBpf5 ȹb_Ge\I\x:ڊP *oj"b"zkj"(d-z$NT$rI}*@Zixf1uURQAWQL} Ђ.@nZZKÃW 拷۷ $x7-Xߴ=߇Է+xvN~:/>o@|ƞN @rA|_ pa@|b q=2Qؑ?o=JT\LQUXSgMYMmTNVJ >DQuMSILja. h :LtW_*g r4 f Kb0)=<CVvY =w7!`OxhY>$b#78HA0vRѐ.3f,4n!81d4#H;jpJ9n)ݘ6*n O%Ԩj0r WšJb; ;FPshd1~ܥK>2`3ɔrZWҘrpן0fv1`հL5E[ҚPNM%%X{0N gsc*&z*r`W:jPz`jSFfŝe:5l-m - H8("v s]|Wז쉌}ï3>èYS7s ;FS1?^rJ֍8)"Y0_s8_,) ̡*f5 ˨zɞnÛ}38V HHEs :uZ)qSu8WW&7'xҝ[^4S_z50%]5r-]e7j24?5RC[}Qsc_u@;H:,k:ay{|:Lү0|Myһ^W}Oa^`۹^E+n0#]~{/I: oh~Ń|i[V90:zP|N\f.7%cs tbUq%{wܷ ɐ  3M&~ E+\EW9#*8+ 0:v>Oa6awcsolg/ auXwlfsD|4o0{t83TXu֖u?,=6 &, #~&8|,-"~j0x肇x`_/&f|XtX|7'^oWpoWf7QzbJ7XrPt%x@_fHm"h9h4*h*( ('8(-(}؇  h=%va39/0%P~إ/X0QXҎp13b1яK 0"F t%P} 1pѶhX>V>eNf8ਇ&~Ȃ(量(7~vh .y7Bjs1 B#938 c9/39y#8 S9:X98I!9r9(/7R7e:#9:d9:cLi2/4/_H%|qȑVT4+$_K5=#ɍIjՆ3WKd9@BB ym9y)9@!T9 A8x{`z9YBC8ySK d.$BAw~}EheYʑ19~}H@I947@DK78Q82`)K !KdA JC8w! J i8I TId8٠ x9TxI+]g Sw7@*DzyGjJzLjH`PNQMJ\41!#ij  sJujvJ @uyztsz ʧPʧ꧄s{ʨ : {: wP<J av4j=h2b;>Ӟr٧ ܠ  }Z ʬ/ 1ڬ 0ڬ @01ڇ1 0 X҃ S+=گj k:%`m=S<8E"&s-HXBi+9qf4 ܐ t ~ ؐ ͐ ͠ > ?K@ D;F? дB[AkQKO`ɐɰ^ ɠT C˵KQ {z҃pS1t;r+t#Xs۷C ˀd>੪+_*>XѸB1Lrh;8#5hhhY P EX+S[؅[K>{~ol+Ӌ { KB>Y+!='㨂{}{?B7)& X{ Z۴R۴00봸[, l<~ ̴[Ȁ,"{м3*+3.* 3l47LO}0 A@qx!Z+ZZ(}Ƙ:`*+9= $= 7pP Lhuwl9 |zǀ rLȋ|~}[$+y[^5jp"+4iI+M_ܐɝp ڹLl׌Ҍi|` Lڬl{PS# ,wp JT*W߄>6艹c5h+{py}0|'}!=$'}"]/%{` ?C-EMGAK$ Cx}V$TI%F%^ _-aMcme],sQ ðzOp Pwmy{}~-؅=؇P k n*2RٌMَٙ]p pm ;qسV}EcKh}ֵM%,%Wc* ;< =ƍͭ }ϝ}M-ؽM-Mm='ڬmXc;T7!xӡm㎻Gs᰺HZKB>[z.>ޤ蕞*.7颮n뫾뽎댾SZ MjN+}Nn4JBI%H3\K2h>1G~` _}Ḏ̾.=)N9@LXĻl>> H-!/#O%o')+?#'^b.ʂАV; eo^>gH=o_JKPOVRU/\Xa_S[0X=r"SW?GUuw4un.K^䏿?%O7:䓨/0[c45Oa}cC}o=6`\d\mA>??J `~@Ro\^e?9*kگaN8iNZ9 ;ذ@/NN"A'(i)pbhc&/6Ps4 ZY+J/q&K]QigO ChQ!>4q͜tY>>/a$p M06.[jy[үE+OAoG赲 4u L!>+l;UЂd8t̜W vREf)h'`g-yhRas67 !^t|z&t5bh<}Oz;TVOV#ש_\yuw/4$GG3lhzs}fK.ڊbnֽeV[K@8包ȳ|L?/5f A(FRkQ]([eZ.A/Aܤz-=%.|㚂ȁRh;"qSFDSI5ԝPTS !BO\#{$i*˓ߔcQҝc"qS ;GM"Ǚ1$-.=Tb,R=f5nֳ,@Yv-fEԢumkIKZʶ)Y[tS3^A~G"٬'ASu[/V- D>0`+׼ /zջ0|{׾/x֕ꖷ=L<7x.Kl&WQ4l2Sz =.E\A=%F;G,bVR9=Ohf2LMSK( eg\۹ 8aKnYOH1DP9 b.K|ob΋t^;O*xWDezʚG0 y X4!#. a"ov4 M#+ȉe8@?B}O[c(fTZHfSd4hׂ!xϼl!Ђ^` i h@ijN!hGJ?F >DMr+wX;sM|i-df<7‘!!\J7/"[16+qf@B+)qn8`U4sכv+Ulsw3I+NAgeeqTf ]#~ lHw^bdUF;|}h;@yw=x;wG<w|x "7u8N#C ,󙩚aT5<Ùţ%u< N^#:HRɞ}րh X3jg $b <uf2l5y7n6sߒ#趒hgs߮?3C:K2Jiz;&K='^*r4DTda;1Ԩ : ,.lB5%ӗ+J$a>&2)[0012$34C3|8x) nJ3YBREÜV4TdW\EWIld)=X ij$ePL؋ھS.?~ɰR\d˵\˴i[p˺˵$ 5!Z4+bɿ>5)˜:DGlFZ+9)(2FB2 k[% R١md3ux}twHxZuHHH8uTCc#hi[4c;2kdSۙC@1`3pJd3p(02!<'Ky\'Mшte]P]ug[g#]MkXTktXQXWskpމW#c4iô6A2 L d55):Q#OqЂ5_t_HM "a"!.xxbhz$ s1L"" H0gTЗ_dԚ8i>XxA;<=> (ADTZ@F~dGndFvS k*3f tN@IRP#'pZ(Qv!;XF:~4D^_`abYMff]i<XM"zFK^|LȬzw2X-RyNԪz-ΚcEZE&[LfFh^h ]Cdh j x h`krn(¢F Hʔ0,C>aN.i!3j:C5X@Jj6"Vej.jj˹fb*F܏"o'+Dt2j;!ڪ ܥzŹ#k@'XEEJ~ɌlǾ3^0;1NllĖeY "@B9FL64!cJ.x~k=!ԗ^*ီFy$vn> ^UEnWU+AY]OƜJ ^[1%ʙjȮ  ԩj.:_ ONX.p , S['7Gq:i?m }aծ1nR)ΪjinV^LS*硻jК8kl.ncctBKa,gDRω.+78V]7W{X7s9_:w:s?)I0`XCOtE?t8D_tDwtIJgtC_tXtHWFotHKtPS/uJHKuRwxȇ<.u]/]^]'0b?vc'v])pFFSSiSlvjvnTXdj_dD4wFwؓIuNmvwxo;ss||HL8w|x~Osu7UI4ixxxxx'yMyxyRmN}}z/O/ׇ^?w?x?s>O7'\BvZVl'mkHٵ!ɈD܃{gr1S@xwuLLuLxLwhG|sgpu'}7WOM|P߇~P~~޷}ܟ|[p|W>'{>7uh+U937>k6bE@ #x,FkA~!|g<w Zt3.4p&i)p^߿}8zOƑGI*7ɏKI~1gN+I3WDZJ |y ց^q֫kK4h[]A| TZ⼋gYXQdi^5ժ}~a9Uq|gV-o9ӜQFM:maj4fij6=8]ٴV-zt~˄iAu2۾4[N0ކ%;|U2#;So~Ɣ8'RFB`'X '2H J*a>h6U]`fY>bh9ԈO,ࢋ, ePa|}GwH2]6dw\g: b|ҙtVjazyt4a&ܙe& v)ny'|s >1xew%NIוe re"dDTPQL*S/arM:*:Ϋkܺ뭭 5p"r!ZqWh  8P; -h D6ؔڱKTx:LeWo]tmskV0k t[lN 0l?p"q֜raW2^,],ܘaү4[r5#8BXL$R;>NSC-uVSY?_[ȸ#!GW&pƕԊa6XN | c:4ݵ ə-//:,:'/y5߾ n5Ŧ}TBLCLmڪlзt0n@71V`:̅.+oeZBSoR9HeU* 2S0Xl oDcqB1XD)`=a:ۏV.1F#YJo\T̊ʁ2-laR"8X#\%+[WFc'84lQ/ r:ԱyR3eO}t)&e2twRĺILB!&i7Fd7Y}rV4z*!F:E ,.), @!k@Q@50dᨵ4X @ICk餁,5aE+ Lӟ4@PJTW-lQ:5ШEyjժbժe6RlaI!LCd:rH~%K|nťUh,  `$c=A3yA>O4&Vh> QQc-X#ѳFhztRPE2jKխ^XlipyF]:QuXؽnvknuCWŽOzU/ uSO2S[ݲ{'󦓽3kM6Mi"2&7*=[ ģJTg-Y֏/D#&!% nB#(Gm-puܠ[5z[|FA`=dL82=-+a4$r1Zd3Ye5fe 뛚,m jȰ`bŎ8!drf2izć>X[1땪? N d_ _n:ժ^5Um|ղ;fU2iC?x?5_L:l_1V~C8]k6,pIge~l>XǠRZ:풘H8"Y% ׉e/<6qx]2\\&('Ʃ&+9&Z@)_[<0N>\:[>T/o[McՏ8#D o#?򋯈[`t>{ϞM?fk?o?DŽ?o_`" *`eEM$D_^ ]f .`b 8|VHC *'` *@ ` `҅ G JB:Р @ b "a F`2BaJ!:ZVjZ2 r!YN[7Eaap@U@@h;Hh@ 71U,fE5m[%b%j"Dḽ[&Zb(b&.n۝Wy]JPȸ8\ɉ0X EDqLj,@+ (Ict,!jH#ph#CH>E)%;`o(a 6^(@ |>4j>Y?=ƕ>c@@#AccB"A:4#U.6Na-yUøI 5aMT$p{9/B0#,E5:F@#4O66^#8D5$Rn`B9RB%C)<|F4@0@OcRC@$Pe47۸MN6ϺbU[]N+%``Wa~afS`B7-f0!1&RJ~O\5FXM%ZFe\M/E(@U,4%6%R.W4ZC4Cl2nV#gL"g8c%P;lDlnGfRJRenfesfs2l&jL"Đf eb5Ef G~_KJ~4 !#FL_e՗oPS}zEu[߹Ug|GbIK3NhL*KJoMJji%4P5Ge:.%QhO^ $9Z%V:r4P6c )Sڨ[>S*19ہd"x{fFVY}ݧ4IN-'Pq (f9)6}}[ed5Нhh)n11I`,,@`I*]vJbp28) B' .E`ߗG }Ys_MFZ$d \ Yբ&r̡oV+z#rpS Vzq&]9kej)K>(3dFn8C XUpNۈqPrkqHjq@vꙪS雀'@`"]bE)Yi~ ea\R~9+b& >u[P╲$E\yyP$Ă,L)̂,̂,)m)-ΞB:CVB,H-*m,&-,Dm>mf-v֦c} YMekjd}f5L-7r"}" !(J.k|[Gi6߆U e(ip Ť+Ik~e+Ynnn7"ۜf/RB&3ĒV6!b:f, Y8.ʎ(Z R or`& /oo6`ov"pگ0 * ;0c0[0 V/I ;$$*%a 𩲮Ȯ ێNU(N,^Gv'ȪWpGޕ֮ ?oPpfz6x & {: ŏ'qTf})~FXxY#fY9'_"M:q*W2"y񱹖[[D$LwFV U :$z + !ikaU)1ppo%+,. /Sټ2.׉ѧy (~!'/'gl5grc#&f|.î,ڧ茮biz1Lf[^٫=w;/f(t}:I}rF5KWȂ)|e{ven)\ڪL ^/ XC]4!j 2Y238/n>rT5k |0+sDǶPBiin=C=#2h4zM{.49"NE]汰}.i0kC&gP疪EC?lH/4ژ1 rA ̀J'sYXc-. %2N[ef1r8흽Λu j"+M`tBvYY٩tn봲fY[IT$BLaOxgy/aǠ܃./yc|Ly~.7|7F{}7~u^8y8.Qwc7.w|_xPxOx73]p~N7{G9yO~x/wP8xw)<`Z;`pk9g`909wy9y99yy ?L*/((Sz[czksz{zzz[zD@z@:z:z {;{3;C{GK{SO{[c{{s{w{;vldocking_2.1.4/src/com/vlsolutions/swing/docking/doc-files/dockview.gif0000644000175000017500000002307310573516344026415 0ustar twernertwernerGIF89aH9BBBJJRRZZZcck!k)k)s)s)Z1s1{9{B{BJJRZZccksss{{s{{{ƽνޜ,HHp*LpÆJHqŊ/jqǎ ? Irɒ(OLr˖0_l8͛8sɳϟ@ JѣH*]3HJիXjʵׯ`ÊKٳhiQ Kwݺxw߾yP@ 0P#?h`r@3@G0Ө/XpC0dM{C ssw`PabȡH"&*DO@ =eD\=k`B1ddK:yYf<ٔU9eekyIofk&rItwZݼq )(zj{0(*|W`6l r`F8*nx!⬴h Np]30,4߬s<3@f$)d0iiF픡Mi嵤ek[rdkflz.n]G   {&Li78 wJjA j"L+,()ۈv dC'[:gO6u٪j\v l9.Oq&nsuB'y|z/yzM }0 Op&Wl1b&ĬLʺZ\&@Ѐ@3ֱt$E&iiҳE;MjRm-Lᠫln%Tyԁ/@aniz}oOVY*ST! AB؆&Tu dۜHkY)[Zݶ0 e xRaдt%]iktzz@/h>] ,-fR~<9vVs4ll'!@*‚@NH: , 2;X-]KU J;&۹Ԥ.my5d'Oz'_r[7JBbk) Ήz7*^b'@AJ.D'YNΕ tVL72sfv3QWM!lɬ9 Z ('i"/p(/D^} ~HP=X*iJaN1B8A\q9c ґs(U1ҖwLBUe.Slda4$4 >)Zy|$i.4llg uғ hxH(Rͺ02A9@AFs9ˋoRK (+8aP5[a]L42Mo{BԴKX 2>eBksS[@RS8邭l3Y}Z^Xޟpj2;`[taq105E]ѩq@wҼ,@~dXF"6GuVњgBcH,7YRjͩehX۪Bo;˭ˠ+ 'Ȗ(@A,K,+b cP>fEkcwq,~JSd: n3Yir~ߧEmjݖxFrmMS_[ІlUq+aQM|PE?LtWbou.t zrykPPRh oa X3CnLc´4 (j3ഄ^mN"eJgMm: 6x|9袂J5ƍ(K>cB'Bt5K]OD )Y?j\i2[cP{ QӲL2Q뗜ݕ,3rukT[I'S:pV@=P0v-UQ.ŭ궋}FvcEVl>#1 )~v1hV]20?sRn7v@sE77AKVoMvooRFHtHvT&ZZ/&U7ϓBv$qQ{q>qVg5QSEVEE&*chH3 0c80dH @nҴ}1iMLGU~DeBeZug&Mz p6OfG7hgal7qr>)(h*bK#23cwF7s}7SXS3#4AK,ׂ.dTYjZz`4frbCґC9tU'D[lDVaLHg!'QQ(mbr#r?cDc8XmhS;dryw_t_~WWHJU`z- G/%`'e\lvG4vNV'E"!F~|YhRn(XS$#}deoO4QT/DUZNØuZdcIı`_אԔ1=BCUq[PJ{{&w7Ks13?&)"Kx2c^LI>ptYwx9q:?!K1—iJA}8;3q(AoIIPoљ9ٙa!oY 'љ)Y#IіOyIy̙0"A5rYٝɝ)٩޹9ٞ晛YiiṜ)I9YI@j ڠ :ZZ F#j*#$%'j( J.*-:;z/Z906q !I)L:6ڞٚ*FZ)ڥ/F 5bc ]jYonS+z(ڝjZiJܙh'a }uJm+Y \\ꦊtڤsz q rzڪ ^:xʩ*g? zڨGʪƪɧJJjjtu:Ѻ9VZKjJvzH=𩮷J :i41j5 蚥SڱZ{z+[ kڪJI;*BHҩ&۲xzʮɳF۫JTZP[2 *iڰJ. ` l۵㚷w[kpu{۳R; bZ%zQ۟)[g9;;(.{z4dy{:zfK#3[;KK˟뤐[A[{ꪹk<&{{~cJ ۣJʲqzk;ޫ ʚLG [{+J[';۷ڴW!l}wKʿ2ʾ+ +/Loڙ; k +zlj ƹ)Vs[K+tDʋ˲f=z[ǂ; sʿG)[ZKlJ+Y:ȸ*p,;:JܸT9̲"iLkȌKèY L; pYJ.۲kj <6իIxl -\Ū䬹"+˘I+&u 0[5X]#]2Q}Ԙ , =7NXLnۯNtZۇ-kWtOM z|2<&M^̹ŋmp׽$n<+\KsM̳N]*$!&b|j+o`NςݬmD|F\.~g먬$. O}-֬n<[.,Ǐ ߩ%\j}MUƪ׊̻}BZŲne~.u]m+|ju5t/h~л<( ]:|P/qЬ-DODM@ϑݧ=i<)-ioѡ_^/QO=VYN-̺ ɚn=lᯯԃS-^>4{7lFX@I$dhaBF,8pĆgpѣ'/JDbɂ#+fPS&|rC$sR̸2H=LJ&a$hs'R,gUԚD m0Ǝ Qhѳ4u\fS=q& ϘYe+oۃI25mNN=pk t'X  TS\pC!CvwM֭eMU[w O49*8Fbmxѻ:ܬCa.o>ɬk5W˸䚵&Lup/1N+n RԊ.7(lހCCN* [1-OlCRT ,[ODϬؤjJ\;Vu-K]N,D1CK-- *< =d\ HlArC41 =LsQfsӱR̅<-cT.%-QBaD9?LsWc SPHdQWaC+Yb$A*it1t'E0*2234x(]#Vʢڄ;}KGNu5C-+pO 6L9sZ}8"Oӝ64҉LMc_wd46IR3̸e$paeo^iyLSdgU( -v8Awsu"|_s 9J5TbܘW8@qEMJwȝ f`@ 6tRՋ}OR/=qg9VZCTG?\TD:i,湵A.) ܖ@89rcZt'ڱ#[#qNW4č1o\CJ#8; *M=\OlR\Xh+mv 5CqB!I1## uLF N'1$rW s~7KV Zm.v[.i ڂ/V_z.XJn.$ݏE3b6+IMta ͢prJx+U`Ìx7MaXYK&L|3N6H/& odj@$|gGPK'DM䴏'!5:)ʧ<ʸ6"@kD5h0ZL@H4|H"=?/tYxE.&r&hM&s{LטJ2Q4QØ6y0Y2T>BOD>(ĸ:eT#cȭԓT;*-LӾGֻ$4XŖS,X[Z-\-4Uٞ9:]|պ)ɟuUD}Wc@[^?RLeLZqBMcP)UV= 7s%|g &}n7ZRUFKK\jI.)u[ #NߦlqV;Tv+z&:E"nH,Fy $%3ilfX>(]S!mTsY&5kTJ$`[VYx:Mжk[¾7Ep +"#Ew< ;"cRz=(J"N0KTՉ+mG S#s",ZZ-۶R)GW'u2 Z;"޼vZwζcǸE[Kif]# Ԣ 'ڏۜkKU1Jl$⻡~/:X`1[Za׹눦.Ac[I>TjxAk>;Ow3ѓ.Ï7+RE[:vEy.nJ=ռɯ/2 7șvNnGݞbypxX7mȆ[46 I\SEz{ԁ:2o˽6msAN?kh\o~(7PM w.Uc;k@mNEI7j%*g=!qn !˦ 16$ܡN 5֛9oa+jùCӹ"Qx Yѽ;9C0[s&t2SC #Rx#:izʬ[!6E3C,9`?42:B2t8q {Sg;!IB8_*k*B"”+,(>I1dG{ZR5l0T 'ɺss>&*#-ӫ$K'4 L0úl44ޣ3:O8۰C8?RTS6F De{󲵵[D6?93+52pF:,,02![c[soG7C#ԯ3=Ls0$AS3@^B0.SJ#GћgʯRO=0æSV)&5cı(՚CC㰌rz$i{:tң9棵˜!(S l.3HmH.{<~+/#Z$G CsQ9V BFk5kC N? HE2:ȰAsIS/a$&.tEd bS:+ \=s,|:14DHG[l}ET%PP>u6;eADL ClCFFW{o17JI@BK÷rO ?q7|#{»K2s(]yO04&Ԭ5kp<Ĕħ$졯G\ J:͉1ў|DU'CƗ <(ŤE%?4+;k+ˍn:$"GS#D\ cJ2Κl93%e;*2썙S)bF ]+RT1OS̥9%HFғTKTLTMTNTOTP UQUR-US=UTMUU]S$(pUZU[U\U]U^U_U` VaVb-Vc=VdMa}opiVjVkVlVmVnVoVp WqWr-Ws=Wt W(xWyWzW{W|W}W~CWW XX-XX 0#(}XXXXXXXXX YY؆E;vldocking_2.1.4/src/com/vlsolutions/swing/docking/doc-files/float16v2rollover.png0000644000175000017500000000050610573516344030126 0ustar twernertwernerPNG  IHDRabKGD pHYs  tIME  $Z5=IDATxڝS+ r|lEluTst.Gs踼ހ(u aB\]*d/׸k͔V$KO}< |z`j`  (!V86߆uo^w͵i+Xڋ}L`9=P)]hRHN0LQ'1! *C+`+D=^aEXxE^QL&6F+hl{fɂb;rۣKzVk&Dt1& 1 B SB pD +e,mF k1sչG.?(񼧣6<阀0 ^+6@o>IoOˏ~C?c_?nC:|#H Z fz GHp<<v 2ġ d` a(C:TG:` t.nQZb+`RLH( GsFƧ1v80>~cHȆ c!G- #$HDn$&7Nr %(G)R*0>V2`*UYye-o]X1!`.hQ%\X ,*01f|slL:٘1td<GӞg; O|'?)P}!PA2D:QZm(F7юF GOHҒ(?؁sԃ "0B;A.Yz{×eMoӻ#Ϙ2fÙQE-)d0*`'16HNgZug[лff={O k<;PհlbJ׵Bͫf+ b,B-smjS~6umlYlmWL[)K05?| \{#4qeh˜h3* hbҴGAZ c3Ř[]ܪVlhz_{2ū<5BZ~q\ ~pg/a ¤M c#F'ښN KXvu)ش+_c;f1y ƭCp EM?0ry!q]$GwQEWp+ZQ@ JDH$Q(8xk0Z_B ߃O| /l~5Ҧ/Nu;_RZԜoU}jɦ}U,3X`uk×[,׵vy_16czk`oپb0ga!OۗXsZB4oA - E+Ĺ(`"EY _~t]WW5 ˞v.mhՈM!i#Z5MYNJ#/^r 5j4ekNٙKRy+}҆t,2l; N߲o [օ?ng])La y!AV/Uy^1ˣ)!fola~Q}!1OO妎'# b6$qJ{w=ќ7x Dw¡E ՗>:ScL]2 aN\`y~?0喻x/v3=c7 N L(hCx|0{$ |F0`"v?7aVla|V+ZPZ W7WN8aXXZwO%VZ+H%XO -)(U[3%ZXueI؄ | Ty\6ca|9[RKSVv WX|[f Uc ` P^'0n}p~71/N12/h3Xh6È؈18艌hxH-a+hG8 (;h(񀽈h؈H،؋ˈۘHhx8q{ K6g`fYH\RVx|xf{g8`ЅH' L5E UP2 2w( p-+i*M09/Y0)6MQ66IIJ@<;IS;)XZ90T1)^y@T NUTW0g9KIG9K1pɗȖ7 xY]Jٔh5sX`Jјhv yVp˅t 0}R; Б P /QCL<0NP*oyȉƙٜЙ9YIɝy9IDP*i*ELL`)yɟIiZ)ɟVy`y@Kw kЏb`agz|zЙscbIDP ;; /#0P*LXS*N SJRzVUX^_JZڥejahnjSWʦjZxz:{ڧ|zJzzʨ* ZjzzZ 'xdzk0bСKP҆bV`0* MԷ;0 9;=z pA:EzIQ0R܊d:uZ`j:eJVJ튮*:jzʯگ;[{ ۰`uJ SJ.tn1: P ;P Ț s *B@/*<Z'[=rT@:T[R VTZ۵\۵Y`[b;S[fhkkKi۶[rkp{^KNyz۷|{~+;[K{M`CvSx nYpK`f PE  @ P  A.P*"H[LF״NK('Tpƛʋ˼ۼK(ۼһ'׫٫;;[{蛾꫾RW;[k{ۿHtr 2tnb0V`3RK, lO@ `fE% B@k1p*N0< MJ${"Bĉ¼}[)Ĉ"E(J+(Tā;Q|ăBk\Ņ2_|eIfpqsr|tv|{( ȏr)ܼ,)ȃȈ'`:C7mV'd0ePɽON0 # jf` j - ~^~> n")%n+;WK857^:?n1Nl?JLMN.[;NSU;QO];_~jJ+'?P+S WVTyۮR[x.W{N~耞*~y[s.V|+Pо.{.޷N~긮꺾ŞfiώNn~ ŹEE@~0*>߹10N s7Ll2lva3pqo A/n  _O"2__/ ,:6O5CoE =o7OM,0vm'TU?[_Y?0T\V?f`eO]Sa?Z^O_ov?|~vf?V('`*#iM0P+`oO?_ȟʿOMV`۰ ِٿ_O//ٶ 8p[ *DpA J!D)&ܘqĈ7FɌ(M\P%ǐ-E,H̎u'̇BN0(Ҕ.eSQNZUYn͚l\Ŏ%[YiծUD"]xwo_%p†#^né_}r/G}/n !T@r0i4F'0̎'.#Ȼ!<M<[LKj1pOpϿTr\'rA*le+ ;ၢBp0JOE_qoGLH% |rP(TK:j5TLIN "16WNϓsN׫qGGgᝍ)FZ釳鱎:[h8& wmC *!jX+ZH&[bEu!b2 _$\Rw8qˈJaB*J%*g3J 9C)<Φ*8PY-Hk_'ְؕV^;.(’2$D)n t"HHA,9$.#]r0%+LVʘUu@sP,U >vxG[a}.2# Eh)Eek$Ca=`O_ z4@#.Wڅ ȆBь(8%zN_^Ԗb.E]P6KHB41/*H"*ȉv8Nӟbt!9WG65HI/tX37J$ w\GA|+J;Էv k] /z4Zg1[?l{b~$2wӣL򽂰-:W^7W Sc qxBUݪ:X?ϲv՚p+Y"5iF{Iԍ~penCȸWӴ,:ra$F(]3}ƘKգ$9}^qr#tQ֩QTI"Vժ&߈OnWfG*5 MaSkn3s!6}3 #bn/ [) XEm ]&++g b#Usf~V5N@/K}$&vvwbudzV5(Oߪc\+>h^)iJ_vM=Yx0DVm\"WİnoscP \Z *Pw^ nۧsvzHggWSiy gV6M1bB&Kw˫dd mgٗƲsQ5=U{sgtI:೦Xe7wA?Α˻#S+ @s;jq9;k2c2Q9+?c0-*>ZS=/Sa!z9 ܳ@i:({;4oB= |@҂;4u99?*Qߋ#mb3A? /9 +B#L# (@ᾢ:iz>C7!,N:"8+3ģT@:,b R,ES| f8E`& U|EXSLEYų@]E^E_E` FaFb,FcHn Φ$݄N$l͞MKMӜL MKLdLONtOMߔJ ٬N:SR-]S$ԫRFMTLRGR<ROՎ5RLF%K-NT?M)=/}TKJ6MUSR ?M"eUY5R@UZETy UbER4EU+UYcU^TT13PaRgpJWSs-bmvUbmUdaџU,jdiUl{T`C]uWxXtWq X|-X2Ϥքu~eӆ5!M}ViXhXWU]TjדV7,PX}YMYpYWUΑUXyXנ]XX%W-Q5T=םu؞ Y5Yٌ%k=Yڜ]w֣ڔWXZUVگ[hڴ ڶe߁`[uY &bbP5bZfb/MY2aM!>$(7.-_1.^ .Ɋ-P`?6e5>&89c5FcYmc C>JbD.;d>fdL~^a:A\S^S2vbtd-e8Ye.W.dUT>dc?G>b``Yfc.N@a7e5F\_5?V`jb96g^Xd^~mngfiVgtf[甩)di._f}g,a.tVh>cUawv]~gFh;`Jh>h&cO&i+NZ&eo,F vgnhVgdMn%a]~hch0Vi~hi^^deNaZ^~ihVd+_gj`vUlhg\~ˆ&Ⱦ麎뼾^lvm>kņ.fi.mnӖӤjflnn^bnl휆mҞmllifjbnFonoVno3ރ$&oinUlo  o.oeǖ^ nn&jr~m'pwpoq$.N^pvh\\Fr1q*lefr,$/W6r):'srm'r*'nn8m뎥j"7Bg=sCmfjYl;4>75!D7NOI"nAt>`K_uDsUuFwsE!W'o$8KJ.'[VEguMkoJH۰^oWrhojsss~Obض* 3j6 sbTun__`uL@w[.ìm0prpu_T/xdu)hD 䲵]6Hvyvm9˰1]cyisZ9t,١Gg4x7RWw.96G4{.gzgxxzR/w({bSݳw{·q6G|ZoJq({tG|_^&fWJՙtgw vo}FsQ$v0@7Տ}jQWxz?#$wyo^s||x%}azl VA2dˆ.J*V[~6`7?mĺAnBL,7tSџW ;k̜ լ-kήV6tck\מ'>>;۝cGn;鑇>:xg~|鿭u7?c'z( szH}p\gu9 ~u .8]v|-Hn$h"G"I؞ax`r,Rbjew)v)8^oV3g@ tY\*bP.cȞ4*٦I}&6dXb]: 'UR&(}n |ziiR`o'Z稍hR'Bw梨*~马\(*h^k[USF8Ǟ\X`Zc8Z~k ieH:߹bim[+-/ [nJ%v;뼺to6e0 oŮ m !ӻ*"Zmjpnlq:3,p-6k+ qfn3{,L\Kusr?d^O-ug|&[(L>lpNH4k_-HG u݀{mMc&[xbx. 39Z7}6@C,| qv޷}v m7:yi9ӄÍ|^<㾗.EUoo·~m::|w}>vu1/p+'3]w D뜥ʔ/ H{3>z=0bPU.Xk Xf}^<9{7!{c[4%EgOT6)I`jm$fS8OaӚdf9Gٴszt;3 tRNeYA2$g9<@hI7ʓNhEyυrϡ 1:2aj!CE9&Ԣ)NKJD0M/ʖtHԏIs,*@5șZ\&I1g+jZՀ*<*2)P2u: ?ΆSuDMƵz yU~*U۩նRSuܛ\)͛~Uc] J X}AjH uAsY |Dg_' ,6'm=-dZS]Ŭaٜv5M^][,FwMhkŽrnu}K΋t^W{ \~pͥmw֍w]+t(w^n0Ju0~!檷JUmTHS+TwXR1u5fp?ԡ.]c!-H:or2cI~_ieL)q6.1d!XYd<*ә1vꖕ6'oQeA) 7Rd|Coۆ0Pzԥ&uM-SZժN5WYZֶq][ըua-l^z.v-l8ŏ0 fNZN*<p6-q>7ӭuN4|M׸FlsE29\C8:ғ3N:ԣ.SV:֥ i\:S3ye|9څFcl\n;.ӽv;~޻F.57/8#/S<3s4J#Vb%^b9db6n'v"((8)** A!Aab a<b|RG11@#3.#":#46#Bb5FCZ#&N&nc78c)n$9c:b**u@`,-U-ab=cJ_@"A"c "dBBc4:$PJ%&ZE~#FF99b E6AccK!(dQxa-Md@bAAe">OJ4JPR6Evc8(.eG6GrݜI:ߎɖKV~e-6X䀜M$[e3":4eDJ$6f#ivQ8j_2S"HG6UjeңbbL e!QfZMZ b2j[e"eD56&au%)fk>e+` W&Š  I'F|ʧaЧm}2D~|IBcNf&3eO$CB'] h%7]d%9*)Zh` &U&r`o^.g ơ:}gTZBĊS'@ 耲e2F\Rc]2 eiZE*b'R(wZ*bScxDaޖ,gynbKd"~gDfh@F(hZarr&6$h 9iv"&^eff6`qz =BZWΘ'}iz))*Ҩ'FXeީr2g.gRt )%>'R&zgNiIF\a Vr)gLPt**Χ(Pc Bvުt&D"ii7j:Br;zh&c:OD*l)>lH) (rf2s*bVcN␊lr+G"&wj(a*!|Aိ^jb,vLj~kgЊ*Fli+Oj7"頂ժv^)z۾:*hl2>KRl-оmrJê*m1eAj!6m2$D,QVg^,ewBe*+!Mjm{jϩ{nj|@-.(6m r"fv*hf>ucvn$wJZkVlfݬقе !s@bAA:.^vL@䞤ccdc,ڀ,yM\lNrl\z톬]R76p#+Ro)o"oz@/ In򨞪kPBd]b#uzbb.,y&gn.+/Z|zM몥r/"i ) #.f$. ?+mWha>ay0I*OB\ og1Gr9+Ho̺b$#f"&iߪs.RobVC++z.+2L:,2-ײ-ݲ. @ ,or+qS 373?34G4O35W5Gs]6osvT01q͖J2WZJ;3<dz<6xʬι1_>3?XV a&A#!B/B74D4AD)k8-:Wc43~:rFa0IH JP4?&rF A(TO=OKGl~s8kN23MODdVn8 Xu?P=r>t#?XC>4?V5UlڳUE.rTYoYKLZ_V#1\g[]S55$=^[Z'Sߧ[C`bsgWox18?^,SSK6FʡH'd"govP5WS)>;LY#_udo_lvgvr6-lrR6z4Yo2p4gsP*lr~2^ip7XCWN_vfQqWa#wxvhE6*widGL5zS_ax˶rznxvx@c7o3uK@7-8q5?w7!gS3 }7sO2kzoG[LO]ɸ'ϸR8R/5dy3jkc0+9~/a6Wwp8gu\Zr3 S0tCΖScHw93x~9ۄ9L^th^Ec]8[7߉6W x?:7O%:y ngCMy7w9w:]SVx# {nzc'8+;SPlɩFlk\*y 4G}v|KRi}$F~zj:a{R9nKXB,)цrEn(czI{0 Y2lįhBʭ~6,{8+VRGXSYXe4N5d}SN`S:)OHAVpeTY5Yޖ 2D=vwoDksJ$^Ww]6$ ۉ9Z;u[ OQOvXnY%ZhU\Ehq;"Cg~yiSFڡdQ/^Eex>ޛfN:옹WpVWQ P9*/<6QjsIkoZuArXe!;Ϟvħnzu);C/e7']Ez-m;_ךgn?wQ^ wM߱'7՘xo:rǕ7u`:#= ~ٛ_紛{eWM"(}D迪o[JˠyL(9+! f@I3\ ɧ:_LӌG"ml cG8E#DxS!'i/r߻C2e=suhF22p2D]Ę K"HEZ}}r Cjb)B;:{|!fCWᰐ$!==!qI3I,FIed,c?iqw`## FzQ,.6 TLA3ZG\u-3O+Y~3{t"K=#624*L$;IOZz$bN$R(@@8rF9%K{H\>QvP C~2èGͤr,Mh8ӑU]EK:SRJiGWJT3Oܧ?9J=T?lX0²15*:n4)*Ӭ)V:UX4#ESX25gի߉4Tejst)TUzm`Է-ծMk5kRJVU&[J6=,NyҝYxn5-Th>ë\W#.cA1 bN׹=l{yVMeEx'[P ]mxZú ESlk\/{˚7츬Y7%%;Crj^t'J[EY!WŇ!ou^?GD0>}_֊0^quޫ˫ Pg+*9TMCǘ%/d{xf&gb$ɔr\c.sr3>+G3=#&_nXjF3hCkqLZ$m: &IV);t/gF{z<5g0Z֟je#on1+dI_{{mf|ۭ w^ݐre {S6v]9ƹAo$wkZյN/pۈ.-o8k07{'lx_;/2W;o4Gy󛛄)7cM梏zkN2ǹ57GIǡ>yONhS.wwY]$K]_8kN<#߹ܫ%L~1Jڪ1Anso=u9YNaVyooOws~ƏݍDo_m+i+w}{nw{!؍:V;ϳݻi=E4Bw=J.A~wŽڙ{?<{yǶ [yE/*&ҲKЏOᬍO{|.#oSRh.n, F;,͖(f\0fӸt~0l譬`SPEu +GtpN8pXiPpoo^ cPO߰pP0 /ެ MHn4f|K /. ѐѮƲ)Kw.,Os /wK[+K m pkfpjqQqP )p~1ps ]ggPg {c 5Q A _J!,ӱ9ѭOXJ3)PLeQ,}1 3! 6.d2"}v@RqVmQ !c_j sRmLRr arQ2!"oP [q eHrr'/#r%e1-{R i{ M"1r,+;1(!L-' rϰ,? 5/?+G2/g*C*,'y+3 w" 3/O M&(O4p2D+󒁊r1)W1y8#22 9J3'3Y2c0-s-U;lQ221w#rssTJwTJIe>ӯ2BHB?TKmr0CUM/T(tLEHHe2LJӇOJm4NcdM7=2PKHS!W1O )F75MFSG-C9TR1|IWuKA:'*7ųP?BUTT Ws}X)REE/X)YSsMMR$MUNYOd1VOUZ\WHYutC^R]?R\R["RU\fECSEͲW\UPm_4T1;X^G?buT\a5*+sV9U_2xUb3d9/YdU7f-DmN+fuZ];Ld{Zu;N?uc}eKXqPUY\Vd6l]6ieY4+)J-lg/6RVn["YhGXKveOLuj""mg3mou ?VLWVO2g#$Fml5m >qi .6smgArs3UorLp[wb=ptHvUkk J_7xGvUvW6kyWC7FBy/nնxMSlc%c#s)t6h5[;w[Kvjt 3yVjrw{ojdO7֖wW8y{uksw|C͖vN7wtjpδkpxw8qdwfy5!V^K}^_{AE`wRqwqプvpd $Zel18rm8o8]s]Bc5h븍}~g7}4Wi߳v5WfS8c8M'(<޸#oi9~\8e#YaXQWroxYfAQbxH[h,Y>R?yeE pMmys]8eg9E9KYcG9{ٛ#CO! @Yٟ9٠ zZ#z%):5:yUחٍZڥ_cZgkڦosZw{ڧi5ؚswkVv!A&ZڪZګzVD`W~Mx=ﶨ}VaZ皮ڮZگ[zc}8w/[%AA.3[7;۳?C[GK۴O9646Gu*v{۷[۸[ׂM,Jgׂۻ[Ǜۼ[׻;ř5-^n{yF[d\E4[|WHֺmc +e-Q~7\Nh5;1yyý68c?ڣ-g|q\+^}QZU%ɛɟʣ\ʧʫ!A˷˻˿\ǜ̵6bMBPXBiX;Z`/#|"|`!*[W]=%)}+}¹o'jBO¯DOSIb-\}a= =<ҽvݾA{_I^ѽO"R~# =_]JzH?^C"l6TÉBThq"CRh`ۤ줴'Y\ Jf.cʔ͓)a&|dOf:z ѤOJ.ziUXZ ֩حdj+ڱiמeVۮs֍ 6ۀ(M "bTNn|| C'[֨d,Sɜ6Iԉt̟O :J$ڕ;,ARoㅻxu_kwrś\wJ70 '& Xq|d;<v$I*ՋߒجQ:K %MmgUUMt!(u ZuUFFءo\`fbVŘQUb^utg}6l㎢37d=h 8Ђ"N$KJ9B9RX~y ]1*iq}|8sYdBH'C%o9٠U&r (G{ag`ݩb | jJj*(dFH${y;&Y)I,;, ,+6l.+m^[m^vkm̊K~{n[,WڕS!eaMտ oؿr +7,qP*JidO r"Lr&r*r. s2v(o< ; bt }>3t*R_uZou^ vbMva 'GWkсO^&ڝkZ]#2{|O||/|?|Jܛ_&Q2z%k\5՜~~OߏϿ\=={ٓ=G%{;nJp/ jp?p$,61F0B ZBA k(І;au ސBXD H$bD%PL*^qS|b !qcHF41l\XF8Qm9汎{G@1" (p*PA HGBR(`A%/iL'%)iILdA'5iJQf(KIT(cZR%(U P%.[LZ2̴/IiJaR:@1j*b ,p8zh0s&iÆ#Њ)j;9=@9"ꀁ'?ࠚ@+z˲=Q ׋;*fh.X"Ȁ ld=G:u1h-h"ps4X)>`\[QJM>Z5G}D`_ǃ"B\ X0ĎjtID шL?-G^|b!f:Y$f5pIRxzYZBz U`AlF0~ HP UQ֦67v[)_w%戢]+vE&hmh4KEx ]*uJ +Gc 7) -2󀣁 iOӶtuosg^D>!_ 0 8I\eX!~b.Ii/4ĥ[)针b((FmX z,gZz4kVJ+P(U9ґZS&>o   0I%^bDhTmlcRwƂzWazD~hпQK8 &ZXiA , Gд44P֪ RJTiZ[Jˈ.DUJ]%, G"lgϾӝh]pq"LzM0<@\gl"9î60 u~m,WiK.tD@K7S|^b6">`m';:Ob#L@^O_I2Aa@ۈ1Z4^ToykU[]UIP6Gqxֶxb2LI8=^,P\eteafxM mff9wWs?4'ʘ|(EmģL;.iڦ$ν ejeN^qh6t+MVF >3Yzͦ6R@Z e1n5&< ͯ )}hyDB&VZֆ;֒Lkf?"'| pZ2բDiP}ޅy_tGt9+\u+X}Hp\=vʷ5tzmN7㍿3Jd.vy@Iy#oIwjCik t rLlݼ>3y[{ݽ&ۈ#d 8yY -.XMW+UT郪hO"k ؽ$q] ~oIAF\!A_!a/t' C4T!g}Wx֫SO{l_HqOǾ} f{_ ƿ|YY@;vldocking_2.1.4/src/com/vlsolutions/swing/docking/event/0000755000175000017500000000000010573516350023357 5ustar twernertwernervldocking_2.1.4/src/com/vlsolutions/swing/docking/event/DockDragEvent.java0000644000175000017500000001667710573516350026723 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking.event; import java.awt.event.*; import java.awt.*; import com.vlsolutions.swing.docking.*; /** An event describing a drag operation occuring for docking purpose. *

* This event is used by API extenders to manage drag and drop action related to * docking. This is not meant to be used by User Applications. *

* Standard processing of dragging is (ignoring DockableStateChange events) : *

* * @author Lilian Chamontin, vlsolutions. * @version 1.0 * */ public class DockDragEvent extends DockEvent { private boolean acceptDrag = false; // when accept drag is false, indicates if the docking should check ancestors private boolean delegateDrag = false; private Shape dropShape; /** Creates an event based on a drag source and a mouse event. *

The mouse coordinates are converted into the receiver's coordinates.*/ public DockDragEvent(DockingDesktop desktop, DockableDragSource source, MouseEvent event) { super(desktop, source, event); } /** returns true if drag is accepted. * * @return true if drag is accepted */ public boolean isDragAccepted(){ return acceptDrag; } /** If drag is not accepted, this method will be invoked to evaluate * a delegating event processing. *

* This is useful for nested DropReceivers (like TabbedDockableContainers) */ public boolean isDragDelegated(){ return !acceptDrag && delegateDrag; } /** Returns the shape to display if drag is accepted. *

* This method will be invoked only if isDragAccepted returns true *

* As this method can be called on every mouse drag over a component, it is * a good practice to reuse the same shape as lond a possible (do not create a * new Shape at every invocation). * */ public Shape getDropShape(){ return dropShape; } /** Used by a DockDropReceiver to indicate that the drag operation is accepted * (mouse is over a droppable zone). *

* As of version 2.1, please note that you also have to invoke #setDockingAction() * to specify the action associated with the drag shape. * * @param dropShape the shape (in drop component coordinates) showing the drop zone, * which will be displayed on the glasspane of the DockingPanel. * */ public void acceptDrag(Shape dropShape){ this.acceptDrag = true; this.dropShape = dropShape; } /** Used to reject the drag (e.g. when trying to drop a component onto itself) */ public void rejectDrag(){ this.acceptDrag = false; this.delegateDrag = false; } /** Rejects the drag, but allows the docking system to search for othet drop receiver * in ancestors. *

* for example, a TabbedDockableContainer that doesn't allow drops on its * borders can delegates this management to its container. */ public void delegateDrag(){ this.acceptDrag = false; this.delegateDrag = true; } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/event/DockDropEvent.java0000644000175000017500000001714110573516350026735 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking.event; import com.vlsolutions.swing.docking.ui.DockingUISettings; import java.awt.event.*; import com.vlsolutions.swing.docking.*; import javax.swing.*; /** An event send to a dockDropReceiver to complete a drop operation *

* This event is used by API extenders to manage drag and drop action related to * docking. This is not meant to be used by User Applications. * *

* The dockDropReceiver can accept or reject the drop. *

* If the drop is accepted, the receiver must process the docking operation, * (usually by invoking a docking method on the desktop). * * @author Lilian Chamontin, vlsolutions. * @version 1.0 * */ public class DockDropEvent extends DockEvent { private DockingDesktop desk; private boolean accepted; public DockDropEvent(DockingDesktop desk, DockableDragSource source, MouseEvent event) { super(desk, source, event); this.desk = desk; } /** shortcut for acceptDrop(true). *

* If the drop is accepted, the receiver must process the docking operation, * (usually by invoking a docking method on the desktop). *

* As of version 2.1, a DockingActionEvent has been added to the DockEvent class, adding * a "semantic" description of the docking operation. The DropReceiver must call * setDockingAction() before acceptDrop(). *

* It is still the responsability of the drop receiver to process the docking operation. * */ public void acceptDrop(){ acceptDrop(true); } /** notifies the event manager that docking is accepted. *

* If the drop is accepted, the receiver must process the docking operation, * (usually by invoking a docking method on the desktop). * * @param remove if true, the docking desktop will remove the dragged dockable * from its containment hierarchy. If false, it is the responsibility of the * DockDropReceiver to remove (or simply move) the dragged dockable. *

for example, accepting drop without removing the component is saving * a lot of processing for TabbedDockableContainers when the dragged component * already belongs to their tabs. * */ public void acceptDrop(boolean remove){ this.accepted = true; if (remove){ DockableState state = desk.getContext().getDockableState(source.getDockable()); DockingDesktop sourceDesktop; if (state == null){ // this should happen only with whole tabs drags as they don't have any state // associated with them (bug ?) if (source instanceof TabbedDockableContainer){ Dockable d1 = ((TabbedDockableContainer)source).getDockableAt(0); state = desk.getContext().getDockableState(d1); sourceDesktop = state.getDesktop(); } else { throw new RuntimeException("unmanaged dockable drag source : " + source); } } else { sourceDesktop = state.getDesktop(); } if (sourceDesktop != null){ sourceDesktop.dropRemove(source); } } } /** It is still time to reject a drop, although the standard way is by denying the * previous drag operation. */ public void rejectDrop(){ UIManager.getLookAndFeel().provideErrorFeedback(desk); } /** Indicates if the drop operation is accepted. *

* Once rejected (with rejectDrop, it is not possible to re-accept it * */ public boolean isDropAccepted() { return accepted; } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/event/DockEvent.java0000644000175000017500000001503310573516350026106 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking.event; import java.awt.event.*; import com.vlsolutions.swing.docking.*; /** Abstract superclass of drag and drop docking events. *

This class holds a reference to the source of the event and its mouse event. * * @author Lilian Chamontin, vlsolutions. * @version 1.0 * */ public abstract class DockEvent { /** The drag source */ protected DockableDragSource source; /** The docking desktop which is the destination of the drag and drop gesture */ protected DockingDesktop desktop; /** The MouseEvent, in target's coordinates */ protected MouseEvent event; /** The action corresponding to the drag and drop gesture * (actions can be seen as allowed docking gestures) */ protected DockingActionEvent action; /** Constructor for dock events. * * @param targetDesktop the desktop which will receive the drop * @param source the source of drag operation * @param event the mouse event which is the cause of this DockEvent. */ public DockEvent(DockingDesktop targetDesktop, DockableDragSource source, MouseEvent event) { this.desktop = targetDesktop; this.source = source; this.event = event; } /** Returns the MouseEvent which is the cause of this DockEvent. *

* note that mouse coordinates are converted into the target's coordinates. * @return a mouse event */ public MouseEvent getMouseEvent(){ return event; } /** Returns a reference to the drag source of this event. * * @return the drag source (the component actually dragged) */ public DockableDragSource getDragSource(){ return source; } /** Returns a reference of the desktop in which the docking event takes place. *

* As of version 2.1, this method returns the "target" desktop (the one in which the drop will occur) *

* To get a reference of the "source" desktop, use the DockableState information provided by * the DockingContext. * */ public DockingDesktop getDesktop(){ return desktop; } /** Returns the DockingActionEvent corresponding to the drag and drop gesture */ public DockingActionEvent getDockingAction(){ return action; } /** Set the docking action corresponding to this drag and drop gesture. * */ public void setDockingAction(DockingActionEvent actionEvent){ this.action = actionEvent; } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/event/DockableSelectionEvent.java0000644000175000017500000001157010573516350030602 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking.event; import com.vlsolutions.swing.docking.Dockable; /** An event for tracking selection changes of dockables. *

* Useful for example when * the developper wants to enable or disable actions depending on the dockable * which takes the keyboard focus. * *

implementation note : works with keyboard focus events. * * @author Lilian Chamontin, VLSolutions * @since 2.0 * @see DockableSelectionListener */ public class DockableSelectionEvent { private Dockable selectedDockable; public DockableSelectionEvent(Dockable selectedDockable) { this.selectedDockable = selectedDockable; } /** Returns the currently selected Dockable */ public Dockable getSelectedDockable(){ return selectedDockable; } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/event/DockableSelectionListener.java0000644000175000017500000001134510573516350031306 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking.event; /** This interface describes a listener for dockable selection changes. * *

The notification is currently based on keyboard focus policy (the event is * triggered when a new dockable grabs the keyboard focus). * * @author Lilian Chamontin, VLSolutions * @since 2.0 * @see DockableSelectionEvent * @see com.vlsolutions.swing.docking.DockingDesktop#addDockableSelectionListener(DockableSelectionListener) */ public interface DockableSelectionListener { /** This method is invoked when a new dockable is selected. */ public void selectionChanged(DockableSelectionEvent e) ; } vldocking_2.1.4/src/com/vlsolutions/swing/docking/event/DockableStateChangeEvent.java0000644000175000017500000001271010573516350031040 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking.event; import com.vlsolutions.swing.docking.*; /** An event triggered after a change of dockable state. *

Events are triggered when a component is : *

* *

It is also possible to track changes before they occurs with * the DockableStateWillChangeEvent, which is triggered before the change is * processed (this event is vetoable). * * @see DockableStateWillChangeEvent * @see DockableStateChangeListener * * @author Lilian Chamontin, vlsolutions. * @version 1.0 * */ public class DockableStateChangeEvent { private DockableState previousState, newState; public DockableStateChangeEvent(DockableState previousState, DockableState newState) { this.previousState = previousState; this.newState = newState; } /** returns the previous state of the dockable, or null if the component * wasn't known to the docking desktop before. */ public DockableState getPreviousState(){ return previousState; } /** returns the new state of the dockable */ public DockableState getNewState(){ return newState; } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/event/DockableStateChangeListener.java0000644000175000017500000001206310573516350031545 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking.event; /** Interface implemented by classes that need to be notified of * a state change of a dockable. *

* Events are triggered when a Dockable component is : *

*

* * * @see DockableStateChangeEvent * @see DockableStateWillChangeEvent * @see com.vlsolutions.swing.docking.DockingDesktop#addDockableStateChangeListener(DockableStateChangeListener) * * @author Lilian Chamontin, vlsolutions. * @version 1.0 * */ public interface DockableStateChangeListener { /** this method will be called after a dockable component has changed of state * (closed, hidden, docked) */ public void dockableStateChanged(DockableStateChangeEvent event); } vldocking_2.1.4/src/com/vlsolutions/swing/docking/event/DockableStateWillChangeEvent.java0000644000175000017500000001372210573516350031674 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking.event; import com.vlsolutions.swing.docking.*; /** An event triggered before a change of dockable state. *

Events are triggered when a component is : *

* *

Note that event are not triggered by drag-dock moves (they don't correspond * to a state change). If you need to track such changes, use a Swing AncestorListener, * or override the addNotify method of your dockable component. * *

It is also possible to track changes after they occur with * the DockableStateChangeEvent . * * @see javax.swing.event.AncestorListener * @see DockableStateWillChangeListener * * @author Lilian Chamontin, vlsolutions. * @version 1.0 * */ public class DockableStateWillChangeEvent { private DockableState currentState, futureState; private boolean isAccepted; public DockableStateWillChangeEvent(DockableState currentState, DockableState futureState) { this.currentState = currentState; this.futureState = futureState; this.isAccepted = true; } /** this method will return null when the event is triggered for initial docking * */ public DockableState getCurrentState(){ return currentState; } /** Returns the future (proposed) state of the dockable. if cancel() is called on the event, * this state change will be vetoed. *@see #cancel() */ public DockableState getFutureState(){ return futureState; } /** Refuse the change of dockable state. *

The docking action is cancelled. * */ public void cancel(){ isAccepted = false; } public boolean isAccepted() { return isAccepted; } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/event/DockableStateWillChangeListener.java0000644000175000017500000001213210573516350032372 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking.event; /** Interface implemented by classes that need to be notified of * a state change of a dockable before it is processed. *

* Events are triggered before a Dockable component is : *

*

Those event are vetoable : invoking their cancel method * will stop the state change processing. * * * @see com.vlsolutions.swing.docking.DockingDesktop#addDockableStateWillChangeListener(DockableStateWillChangeListener) * @author Lilian Chamontin, vlsolutions. * @version 1.0 * */ public interface DockableStateWillChangeListener { /** invoked before a dockable state change. * @param event a vetoable state change event. * */ public void dockableStateWillChange(DockableStateWillChangeEvent event); } vldocking_2.1.4/src/com/vlsolutions/swing/docking/event/DockingActionAddDockableEvent.java0000644000175000017500000001256710573516350032011 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking.event; import com.vlsolutions.swing.docking.Dockable; import com.vlsolutions.swing.docking.DockingDesktop; import java.awt.Container; /** A DockingActionEvent describing the first insertion of a dockable either inside a desktop * docking panel (main panel) or into a compoundDockable (nested) container. * * @author Lilian Chamontin, VLSolutions * @since 2.1 */ public class DockingActionAddDockableEvent extends DockingActionDockableEvent { private Container parentContainer; /** Constructor for a DockingActionAddDockableEvent * @param parentContainer the container (DockingPanel or CompoundDockingPanel) into which this * dockable is goint to be added. */ public DockingActionAddDockableEvent(DockingDesktop desktop, Dockable dockable, int initialState, int nextState, Container parentContainer) { super(desktop, dockable, initialState, nextState, ACTION_ADD_DOCKABLE); this.parentContainer = parentContainer; } /** Returns the parent container into which this dockable will be added */ public Container getParentContainer() { return parentContainer; } public String toString(){ return "DockingActionAddDockableEvent "; } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/event/DockingActionCloseEvent.java0000644000175000017500000001142210573516350030726 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking.event; import com.vlsolutions.swing.docking.Dockable; import com.vlsolutions.swing.docking.DockableState; import com.vlsolutions.swing.docking.DockingDesktop; /** A DockingActionEvent describing the closing of a dockable * * @author Lilian Chamontin, VLSolutions * @since 2.1 */ public class DockingActionCloseEvent extends DockingActionDockableEvent { public DockingActionCloseEvent(DockingDesktop desktop, Dockable dockable, int initialState) { super(desktop, dockable, initialState, DockableState.STATE_CLOSED, ACTION_CLOSE); } public String toString(){ return "DockingActionCloseEvent"; } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/event/DockingActionCreateTabEvent.java0000644000175000017500000001221110573516350031510 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking.event; import com.vlsolutions.swing.docking.Dockable; import com.vlsolutions.swing.docking.DockingDesktop; /** A DockingActionEvent describing a tab insertion (or movement). * * @author Lilian Chamontin, VLSolutions * @since 2.1 */ public class DockingActionCreateTabEvent extends DockingActionDockableEvent { private Dockable base; private int order; public DockingActionCreateTabEvent(DockingDesktop desktop, Dockable dockable, int initialState, int nextState, Dockable base, int order) { super(desktop, dockable, initialState, nextState, ACTION_CREATE_TAB); this.base = base; this.order = order; } /** Returns the dockable used as a reference to create a tab (may already belong to a tab)*/ public Dockable getBase() { return base; } /** Returns the order of insertion in the tabbed container */ public int getOrder() { return order; } public String toString(){ return "DockingActionCreateTabEvent"; } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/event/DockingActionDockableEvent.java0000644000175000017500000001162310573516350031370 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking.event; import com.vlsolutions.swing.docking.Dockable; import com.vlsolutions.swing.docking.DockingDesktop; /** A DockingActionEvent involving a single dockable as source of the action. * * * @author Lilian Chamontin, VLSolutions * @since 2.1 */ public abstract class DockingActionDockableEvent extends DockingActionEvent { private Dockable dockable; public DockingActionDockableEvent(DockingDesktop desktop, Dockable dockable, int initialState, int nextState, int actionType) { super(desktop, initialState, nextState, actionType); this.dockable = dockable; } public Dockable getDockable() { return dockable; } public void setDockable(Dockable dockable){ this.dockable = dockable; } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/event/DockingActionEvent.java0000644000175000017500000001710510573516350027744 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking.event; import com.vlsolutions.swing.docking.Dockable; import com.vlsolutions.swing.docking.DockingDesktop; /** An abstract event class describing a docking action. *

* This event is used to explain a dockable action : it doesn't contain any information * about the current state of a dockable, but describes precisely what we want to do * with it (for example, detach it, or left-split another dockable). *

* The DockingActionDockableEvent abstract subclass is used as a superclass for all events * associated to a single dockable. *

* Concrete sub classes are used for every type of docking action (split, tab...) * * @since 2.1 * * @author Lilian Chamontin, VLSolutions */ public abstract class DockingActionEvent implements Cloneable { /* action descriptors : allow for fast switch/case tests */ /** Field associated to a closing action */ public static final int ACTION_CLOSE = 0; /** Field associated to an addDockable action */ public static final int ACTION_ADD_DOCKABLE = 1; /** Field associated to a split dockable action */ public static final int ACTION_SPLIT_DOCKABLE = 2; /** Field associated to a split component action */ public static final int ACTION_SPLIT_COMPONENT = 3; /** Field associated to a multipurpose (API internals) splut container action */ public static final int ACTION_SPLIT_DOCKABLE_CONTAINER = 4; /** Field associated to a createTab action */ public static final int ACTION_CREATE_TAB = 5; /** A multipurpose action used to describe maximize, hide and detach actions */ public static final int ACTION_STATE_CHANGE = 6; private int initialState; private int nextState; private int actionType; private DockingDesktop desktop; /** Constructs a new DockingActionEvent * * @param targetDesktop the desktop that will receive the action . * @param initialState the initial (before action) DockableState (DockableState.STATE_FLOATING...) * @param nextState the next (after action) DockableState (DockableState.STATE_DOCKED...) * @param actionType a field defining the type of action used (ACTION_CLOSE...) */ public DockingActionEvent(DockingDesktop targetDesktop, int initialState, int nextState, int actionType) { this.desktop = targetDesktop; this.initialState = initialState; this.nextState = nextState; this.actionType = actionType; } /** Returns one of the DockableState states reflecting the state of the dockable before the action */ public int getInitialDockableState() { return initialState; } /** Returns one of the DockableState states reflecting the state of the dockable after the action */ public int getNextDockableState() { return nextState; } /** Returns a field describing the action (ACTION_CLOSE...). */ public int getActionType() { return actionType; } /** Returns the desktop used as a receiver (target) of the docking action. *

* The desktop used as a source (on multi-desktop applications) can be retrieved by asking for * the current dockable state (to the DockingContext). */ public DockingDesktop getDesktop(){ return desktop; } /** Overriden clone method */ public Object clone(){ try { return super.clone(); } catch (CloneNotSupportedException e){ e.printStackTrace(); throw new RuntimeException(e); } } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/event/DockingActionListener.java0000644000175000017500000001224710573516350030452 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking.event; /** A listener to docking actions. *

* This listener can be used to be notified of docking actions and to react to them (including * vetoing). * * @author Lilian Chamontin, VLSolutions * @since 2.1 */ public interface DockingActionListener { /** Invoked before a docking action is processed, to give a chance to the * listener to react to it and cancel it if needed. * * @return true if action can be processed, false if it should be cancelled * */ public boolean acceptDockingAction(DockingActionEvent event); /** Invoked once a docking action has been performed. * * @param event the event corresponding to the docking action. Subclasses of * DockingActionEvent are used to reflect different types of action * (DockingActionCloseEvent when a dockable is closed, * DockingActionSplitDockableEvent when a dockable is moved ...). */ public void dockingActionPerformed(DockingActionEvent event); } vldocking_2.1.4/src/com/vlsolutions/swing/docking/event/DockingActionSimpleStateChangeEvent.java0000644000175000017500000001233710573516350033227 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking.event; import com.vlsolutions.swing.docking.Dockable; import com.vlsolutions.swing.docking.DockableState; import com.vlsolutions.swing.docking.DockingDesktop; /** An event describing a basic state change. *

* Baic state changes include : *

* * @author Lilian Chamontin, VLSolutions */ public class DockingActionSimpleStateChangeEvent extends DockingActionDockableEvent { /** Constructs a new event */ public DockingActionSimpleStateChangeEvent(DockingDesktop desktop, Dockable dockable, int initialState, int nextState) { super(desktop, dockable, initialState, nextState, ACTION_STATE_CHANGE); } public String toString(){ return "DockingActionSimpleStateChangeEvent (" + DockableState.getStateName(getInitialDockableState()) + " -> " + DockableState.getStateName(getNextDockableState()); } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/event/DockingActionSplitComponentEvent.java0000644000175000017500000001520610573516350032643 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking.event; import com.vlsolutions.swing.docking.Dockable; import com.vlsolutions.swing.docking.DockingConstants; import com.vlsolutions.swing.docking.DockingDesktop; import java.awt.Component; /** A DockingActionEvent describing a split action (from a base component (splitcontainer, tab...)). * * @author Lilian Chamontin, VLSolutions * @since 2.1 */ public class DockingActionSplitComponentEvent extends DockingActionDockableEvent { private Component base; private float dividorLocation; private float parentDividorLocation; private DockingConstants.Split splitPosition; /** Constructs a new event */ public DockingActionSplitComponentEvent(DockingDesktop desktop, Dockable dockable, int initialState, int nextState, Component base, DockingConstants.Split splitPosition, float dividorLocation) { super(desktop, dockable, initialState, nextState, ACTION_SPLIT_COMPONENT); this.base = base; this.dividorLocation = dividorLocation; this.parentDividorLocation = -1; this.splitPosition = splitPosition; } /** Constructs a new event. *

* This version of the constructor also contains resizing information for the parent of * thhe splitted component. */ public DockingActionSplitComponentEvent(DockingDesktop desktop, Dockable dockable, int initialState, int nextState, Component base, DockingConstants.Split splitPosition, float dividorLocation, float parentDividorLocation) { super(desktop, dockable, initialState, nextState, ACTION_SPLIT_COMPONENT); this.base = base; this.dividorLocation = dividorLocation; this.parentDividorLocation = parentDividorLocation; this.splitPosition = splitPosition; } /** Returns the dockable which will be used as a base for the splitting */ public Component getBase() { return base; } public float getDividorLocation() { return dividorLocation; } /** returns a dividor location value for the parent split container, or -1 if not needed *

* This value is used to express inserting a component with same orientation of the * parent split container (like : transform A|B into [A|child]|B : we need to adjust * A|child dividor, and also [] | B dividor). */ public float getParentDividorLocation() { return parentDividorLocation; } public DockingConstants.Split getSplitPosition() { return splitPosition; } public String toString(){ return "DockingActionSplitComponentEvent"; } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootvldocking_2.1.4/src/com/vlsolutions/swing/docking/event/DockingActionSplitDockableContainerEvent.javavldocking_2.1.4/src/com/vlsolutions/swing/docking/event/DockingActionSplitDockableContainerEvent.jav0000644000175000017500000001271410573516350034110 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking.event; import com.vlsolutions.swing.docking.DockingConstants; import com.vlsolutions.swing.docking.DockingDesktop; import java.awt.Component; import java.awt.Container; /** A split event : split a base component in two, and puts a dockable container * in the other split position. * * @author Lilian Chamontin, VLSolutions * @since 2.1 */ public class DockingActionSplitDockableContainerEvent extends DockingActionEvent { private Container dockableContainer; private DockingConstants.Split position; private float location; private Component base; /** Constructs a new event */ public DockingActionSplitDockableContainerEvent(DockingDesktop desk, int initialState, int nextState, Component base, Container dockableContainer, DockingConstants.Split position, float location) { super(desk, initialState, nextState, ACTION_SPLIT_DOCKABLE); this.base = base; this.dockableContainer = dockableContainer; this.position = position; this.location = location; } public Container getDockableContainer() { return dockableContainer; } public DockingConstants.Split getSplitPosition() { return position; } public float getLocation() { return location; } public Component getBase() { return base; } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/event/DockingActionSplitDockableEvent.java0000644000175000017500000001304110573516350032400 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking.event; import com.vlsolutions.swing.docking.Dockable; import com.vlsolutions.swing.docking.DockingConstants; import com.vlsolutions.swing.docking.DockingDesktop; /** A DockingActionEvent describing a split action (from a base dockable). * * * @author Lilian Chamontin, VLSolutions * @since 2.1 */ public class DockingActionSplitDockableEvent extends DockingActionDockableEvent { private Dockable base; private float dividorLocation; private DockingConstants.Split splitPosition; /** Constructs a new event */ public DockingActionSplitDockableEvent(DockingDesktop desktop, Dockable dockable, int initialState, int nextState, Dockable base, DockingConstants.Split splitPosition, float dividorLocation) { super(desktop, dockable, initialState, nextState, ACTION_SPLIT_DOCKABLE); this.base = base; this.dividorLocation = dividorLocation; this.splitPosition = splitPosition; } /** Returns the dockable which will be used as a base for the splitting */ public Dockable getBase() { return base; } public float getDividorLocation() { return dividorLocation; } public DockingConstants.Split getSplitPosition() { return splitPosition; } public String toString(){ return "DockingActionSplitDockableEvent [base:" + base.getDockKey() + ", dockable:" + getDockable().getDockKey()+"]"; } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/event/package.html0000644000175000017500000000511010573516344025640 0ustar twernertwerner

Events Package of the VLDocking Framework.

This package contains event and listeners classes of the docking framework.

There are two types of events :

Drag and Drop events

Those events are used by the docking framework to process Docking operations.

They shoud not be used by User Applications, only by API extenders.

This category contains :

DockableState events

Those events are used for notification purpose, in order to allow the User Application to track configuration changes on the docking desktop.

Note : there are 3 states :

A state change is triggered only when a Dockable changes of state.
Keep in mind that multiple changes of docking position do not trigger multiple state change events (only the initial docking triggers the event).

This category contains :

The workflow of event delivering is the following

  Dockable in state S1 (docked/hidden/closed)

   "stateChange" requested
      event manager : triggers DockableStateWillChangeEvents
      if (event.isAccepted()){
        process state change
        ...
        Dockable in state S2 != S1 (docked/hidden/closed)
        event manager : triggers DockableStateChangeEvents

      } // else don't change state

vldocking_2.1.4/src/com/vlsolutions/swing/docking/ui/0000755000175000017500000000000010573516350022653 5ustar twernertwernervldocking_2.1.4/src/com/vlsolutions/swing/docking/ui/AutoHideButtonPanelUI.java0000644000175000017500000001471010573516350027635 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking.ui; import com.vlsolutions.swing.docking.AutoHideButtonPanel; import com.vlsolutions.swing.docking.DockingConstants; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import javax.swing.JComponent; import javax.swing.UIManager; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicPanelUI; /** The UI associated with the AutoHideButtonPanel. *

* This UI uses the following properties : *

*

* These borders are used accordingly to the border zone (TOP, LEFT..) of the used * AutoHideButtonPanel. * * @see DockingUISettings * @author Lilian Chamontin, VLSolutions * */ public class AutoHideButtonPanelUI extends BasicPanelUI implements PropertyChangeListener { private static AutoHideButtonPanelUI instance = new AutoHideButtonPanelUI(); public static ComponentUI createUI(JComponent c) { return instance; } public AutoHideButtonPanelUI() { } public void installUI(JComponent comp){ super.installUI(comp); installBorder((AutoHideButtonPanel)comp); comp.addPropertyChangeListener(AutoHideButtonPanel.PROPERTY_BORDERZONE, this); } public void uninstallUI(JComponent comp){ super.uninstallUI(comp); comp.setBorder(null); comp.removePropertyChangeListener(this); } protected void installBorder(AutoHideButtonPanel btnPanel){ switch (btnPanel.getBorderZone()){ case DockingConstants.INT_HIDE_TOP : btnPanel.setBorder(UIManager.getBorder("AutoHideButtonPanel.topBorder")); break; case DockingConstants.INT_HIDE_BOTTOM : btnPanel.setBorder(UIManager.getBorder("AutoHideButtonPanel.bottomBorder")); break; case DockingConstants.INT_HIDE_LEFT: btnPanel.setBorder(UIManager.getBorder("AutoHideButtonPanel.leftBorder")); break; case DockingConstants.INT_HIDE_RIGHT: btnPanel.setBorder(UIManager.getBorder("AutoHideButtonPanel.rightBorder")); break; } } public void propertyChange(PropertyChangeEvent e) { installBorder((AutoHideButtonPanel) e.getSource()); } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/ui/AutoHideButtonUI.java0000644000175000017500000002213510573516350026655 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking.ui; import com.vlsolutions.swing.docking.AutoHideButton; import com.vlsolutions.swing.docking.DockingConstants; import java.awt.Color; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Insets; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import javax.swing.BorderFactory; import javax.swing.Icon; import javax.swing.JComponent; import javax.swing.UIManager; import javax.swing.border.Border; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicLabelUI; /** The UI delegate for AutoHideButtons. *

* This UI uses the following properties : *

*

* Feel free to provide different borders they will be used accordingly to the * positionning of the button (TOP, LEFT..) * * @see DockingUISettings * @author Lilian Chamontin, VLSolutions */ public class AutoHideButtonUI extends BasicLabelUI implements PropertyChangeListener { protected static AutoHideButtonUI instance = new AutoHideButtonUI(); public AutoHideButtonUI() { } /** * Creates a new DockingSplitPaneUI instance */ public static ComponentUI createUI(JComponent x) { return instance; } public void installUI(JComponent comp){ super.installUI(comp); AutoHideButton btn = (AutoHideButton) comp; installBorder(btn); btn.addPropertyChangeListener(AutoHideButton.PROPERTY_ZONE, this); //Font f = UIManager.getFont("MenuItem.font"); Font f = UIManager.getFont("AutoHideButton.font"); if (f != null) { btn.setFont(f); } else { btn.setFont(new Font("Dialog", Font.PLAIN, 10)); } } public void uninstallUI(JComponent comp){ super.uninstallUI(comp); comp.setBorder(null); comp.removePropertyChangeListener(AutoHideButton.PROPERTY_ZONE, this); } public void propertyChange(PropertyChangeEvent e){ if (e.getPropertyName().equals(AutoHideButton.PROPERTY_ZONE)){ installBorder((AutoHideButton)e.getSource()); } else { super.propertyChange(e); } } protected void installBorder(AutoHideButton btn){ switch (btn.getZone()){ case DockingConstants.INT_HIDE_TOP: btn.setBorder(UIManager.getBorder("AutoHideButton.expandBorderTop")); break; case DockingConstants.INT_HIDE_LEFT: btn.setBorder(UIManager.getBorder("AutoHideButton.expandBorderLeft")); break; case DockingConstants.INT_HIDE_BOTTOM: btn.setBorder(UIManager.getBorder("AutoHideButton.expandBorderBottom")); break; case DockingConstants.INT_HIDE_RIGHT: btn.setBorder(UIManager.getBorder("AutoHideButton.expandBorderRight")); break; } } /** Overriden to paint properly the button on vertical sides. */ public void paint(Graphics g, JComponent comp){ AutoHideButton btn = (AutoHideButton) comp; int zone = btn.getZone(); if (zone == DockingConstants.INT_HIDE_TOP || zone == DockingConstants.INT_SPLIT_BOTTOM){ super.paint(g, comp); } else { // vertical button : we have to rely on a custom paint if (btn.isOpaque()) { g.setColor(btn.getBackground()); g.fillRect(0, 0, btn.getWidth(), btn.getHeight()); } double pid2 = Math.PI / 2d; Graphics2D g2 = ( (Graphics2D) g.create()); g2.setFont(btn.getFont()); g2.setColor(btn.getForeground()); FontMetrics fm = btn.getFontMetrics(btn.getFont()); Icon icon = btn.getIcon(); Insets i = btn.getInsets(); String text = btn.getText(); // 2005/07/12 added text != null controls if (zone == DockingConstants.INT_HIDE_LEFT) { g2.translate(0, btn.getHeight()); g2.rotate( -pid2); if (icon != null) { icon.paintIcon(btn, g2, i.bottom, i.left); if (text != null){ g2.drawString(text, i.bottom + icon.getIconWidth() + btn.getIconTextGap(), i.left + btn.getWidth() / 2 + fm.getAscent() / 2 /* fm.getAscent()*/); } } else { if (text != null){ g2.drawString(text, i.bottom, i.left + btn.getWidth() / 2 + fm.getAscent() / 2); } } } else { g2.translate(btn.getWidth(), 0); g2.rotate(pid2); if (icon != null) { icon.paintIcon(btn, g2, 1, 1); if (text != null){ g2.drawString(text, i.top + icon.getIconWidth() + btn.getIconTextGap(), btn.getWidth() / 2 + fm.getAscent() / 2); } } else { if (text != null){ g2.drawString(text, i.top, btn.getWidth() / 2 + fm.getAscent() / 2); } } } } } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/ui/AutoHideExpandPanelUI.java0000644000175000017500000001215710573516350027604 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking.ui; import com.vlsolutions.swing.docking.AutoHideExpandPanel; import javax.swing.JComponent; import javax.swing.JPanel; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicPanelUI; /** The UI delegate for the AutoHideExpandPanel component. *

* This class is mostly a placeholder in the case the developper would like * to provide a custom replacement for the expand panel look and feel. * * @author Lilian Chamontin, VLSolutions */ public class AutoHideExpandPanelUI extends BasicPanelUI { private static AutoHideExpandPanelUI instance = new AutoHideExpandPanelUI(); public AutoHideExpandPanelUI() { } public static ComponentUI createUI(JComponent c) { return instance; } public void installUI(JComponent comp){ super.installUI(comp); AutoHideExpandPanel panel = (AutoHideExpandPanel)comp; panel.resetBorders(); } public void uninstallUI(JComponent comp){ super.uninstallUI(comp); } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/ui/DetachedDockViewUI.java0000644000175000017500000001276010573516350027117 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking.ui; import java.awt.Color; import javax.swing.BorderFactory; import javax.swing.JComponent; import javax.swing.UIManager; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicPanelUI; /** The UI of the "detached" (floating) dockview. * * @see com.vlsolutions.swing.docking.DockView * @see com.vlsolutions.swing.docking.DetachedDockView * @author Lilian Chamontin, VLSolutions * @since 2.0 */ public class DetachedDockViewUI extends BasicPanelUI { /* Note that this is not a subclass of DockViewUI, (to avoid border management problems due to ancestor listener) */ private static DetachedDockViewUI instance = new DetachedDockViewUI(); private Color highlight = UIManager.getColor("controlLtHighlight"); public DetachedDockViewUI() { } /** Creates a UI for the given component (shared instance) */ public static ComponentUI createUI(JComponent c) { return instance; } /** Installs the component's UI */ public void installUI(JComponent c) { super.installUI(c); c.setBorder(BorderFactory.createEmptyBorder(1,1,1,1)); /* //BorderFactory.createCompoundBorder( //BorderFactory.createEmptyBorder(1,0,0,0), BorderFactory.createMatteBorder(0, 1,1,1, Color.GRAY)); */ } /** Uninstalls the component's UI */ public void uninstallUI(JComponent c){ super.uninstallUI(c); } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/ui/DockViewTitleBarUI.java0000644000175000017500000006242110573516350027123 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking.ui; import com.vlsolutions.swing.docking.AutoHideExpandPanel; import com.vlsolutions.swing.docking.CompoundDockingPanel; import com.vlsolutions.swing.docking.DockKey; import com.vlsolutions.swing.docking.DockViewTitleBar; import com.vlsolutions.swing.docking.Dockable; import com.vlsolutions.swing.docking.DockableState; import com.vlsolutions.swing.docking.DockingDesktop; import com.vlsolutions.swing.docking.DockingUtilities; import java.awt.Color; import java.awt.Cursor; import java.awt.Dimension; import java.awt.Font; import java.awt.GradientPaint; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Insets; import java.awt.Rectangle; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import javax.swing.Icon; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.UIManager; import javax.swing.border.Border; import javax.swing.event.AncestorEvent; import javax.swing.event.AncestorListener; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.PanelUI; /** A UI for the {@link com.vlsolutions.swing.docking.DockViewTitleBar}. * * @author Lilian Chamontin, VLSolutions * @since 2.0 * @update 2006/12/01 Lilian Chamontin : added client property support for dockKey, and react to visibleTitleBar * @update 2007/01/08 Lilian Chamontin : added support for autohide/dock disabled when hidden */ public class DockViewTitleBarUI extends PanelUI implements PropertyChangeListener { /* hack to use custom painting except on mac os (ugly opacity effects) */ private static boolean useCustomPaint = System.getProperty("os.name"). toLowerCase().indexOf("mac os") < 0; private static Color panelColor = UIManager.getColor("Panel.background"); private static Color highlight = UIManager.getColor("controlLtHighlight"); private static Color shadow = UIManager.getColor("controlShadow"); private static Icon closeIcon = UIManager.getIcon("DockViewTitleBar.close"); private static Icon closeIconRollover = UIManager.getIcon("DockViewTitleBar.close.rollover"); private static Icon closeIconPressed = UIManager.getIcon("DockViewTitleBar.close.pressed"); private static Icon maximizeIcon = UIManager.getIcon("DockViewTitleBar.maximize"); private static Icon maximizeIconRollover = UIManager.getIcon("DockViewTitleBar.maximize.rollover"); private static Icon maximizeIconPressed = UIManager.getIcon("DockViewTitleBar.maximize.pressed"); private static Icon restoreIcon = UIManager.getIcon("DockViewTitleBar.restore"); private static Icon restoreIconRollover = UIManager.getIcon("DockViewTitleBar.restore.rollover"); private static Icon restoreIconPressed = UIManager.getIcon("DockViewTitleBar.restore.pressed"); private static Icon hideIcon = UIManager.getIcon("DockViewTitleBar.hide"); private static Icon hideIconRollover = UIManager.getIcon("DockViewTitleBar.hide.rollover"); private static Icon hideIconPressed = UIManager.getIcon("DockViewTitleBar.hide.pressed"); private static Icon dockIcon = UIManager.getIcon("DockViewTitleBar.dock"); private static Icon dockIconRollover = UIManager.getIcon("DockViewTitleBar.dock.rollover"); private static Icon dockIconPressed = UIManager.getIcon("DockViewTitleBar.dock.pressed"); private static Icon floatIcon = UIManager.getIcon("DockViewTitleBar.float"); private static Icon floatIconRollover = UIManager.getIcon("DockViewTitleBar.float.rollover"); private static Icon floatIconPressed = UIManager.getIcon("DockViewTitleBar.float.pressed"); private static Icon attachIcon = UIManager.getIcon("DockViewTitleBar.attach"); private static Icon attachIconRollover = UIManager.getIcon("DockViewTitleBar.attach.rollover"); private static Icon attachIconPressed = UIManager.getIcon("DockViewTitleBar.attach.pressed"); // label resources taken from BasicInternalFrameUI... private static final String CLOSE_TEXT = UIManager.getString("DockViewTitleBar.closeButtonText"); private static final String ICONIFY_TEXT = UIManager.getString("DockViewTitleBar.minimizeButtonText"); private static final String RESTORE_TEXT = UIManager.getString("DockViewTitleBar.restoreButtonText"); private static final String MAXIMIZE_TEXT = UIManager.getString("DockViewTitleBar.maximizeButtonText"); private static final String FLOAT_TEXT = UIManager.getString("DockViewTitleBar.floatButtonText"); private static final String ATTACH_TEXT = UIManager.getString("DockViewTitleBar.attachButtonText"); private static Color selectedTitleColor = UIManager.getColor("InternalFrame.activeTitleBackground"); private static Color selectedTextColor = UIManager.getColor("InternalFrame.activeTitleForeground"); private static Color notSelectedTitleColor = UIManager.getColor("InternalFrame.inactiveTitleBackground"); private static Color notSelectedTextColor = UIManager.getColor("InternalFrame.inactiveTitleForeground"); // flags to hide/show buttons in the title bar (they are always visible in the contextual menu, but might // take too much space on the titles (for example a minimum set could be hide/float/close // as maximize is accessed by double click) private boolean isCloseButtonDisplayed = UIManager.getBoolean("DockViewTitleBar.isCloseButtonDisplayed"); private boolean isHideButtonDisplayed = UIManager.getBoolean("DockViewTitleBar.isHideButtonDisplayed"); private boolean isDockButtonDisplayed = UIManager.getBoolean("DockViewTitleBar.isDockButtonDisplayed"); private boolean isMaximizeButtonDisplayed= UIManager.getBoolean("DockViewTitleBar.isMaximizeButtonDisplayed"); private boolean isRestoreButtonDisplayed= UIManager.getBoolean("DockViewTitleBar.isRestoreButtonDisplayed"); private boolean isFloatButtonDisplayed= UIManager.getBoolean("DockViewTitleBar.isFloatButtonDisplayed"); private boolean isAttachButtonDisplayed= UIManager.getBoolean("DockViewTitleBar.isAttachButtonDisplayed"); protected DockViewTitleBar titleBar; /* This ancestor listener is required as buttons may change according to container hierarchy. * The first example is when a dockable is added to a floating + compund dockable, the attach * button (which usually becomes visible as the dockable is in the floating state) has to be hidden * (tech choice : we don't want to allow attaching a single child of a compound dockable) * */ private AncestorListener ancestorListener = new AncestorListener() { public void ancestorAdded(AncestorEvent event) { configureButtons(titleBar); } public void ancestorMoved(AncestorEvent event) { } public void ancestorRemoved(AncestorEvent event) { } }; public DockViewTitleBarUI(DockViewTitleBar tb) { this.titleBar = tb; } public static ComponentUI createUI(JComponent c) { return new DockViewTitleBarUI((DockViewTitleBar) c); } public void installUI(JComponent c) { super.installUI(c); installTitleBorder(c); titleBar.addPropertyChangeListener(this); titleBar.addAncestorListener(ancestorListener); installButtons(); installLabel(); Dockable d = titleBar.getDockable(); if (d != null){ titleBar.getDockable().getDockKey().addPropertyChangeListener(this); configureButtons(titleBar); } c.setCursor(Cursor.getDefaultCursor()); // needs this to avoid artifacts with floating dockable borders. } public void uninstallUI(JComponent c){ super.uninstallUI(c); uninstallTitleBorder(c); titleBar.removePropertyChangeListener(this); titleBar.removeAncestorListener(ancestorListener); Dockable d = titleBar.getDockable(); if (d != null){ d.getDockKey().removePropertyChangeListener(this); } } /** Installs default on the titlebar label */ protected void installLabel(){ JLabel titleLabel = titleBar.getTitleLabel(); Font f = UIManager.getFont("DockViewTitleBar.titleFont"); titleLabel.setFont(f); titleLabel.setForeground(notSelectedTextColor); titleBar.setBackground(notSelectedTitleColor); // adjust minimum size because of BoxLayout usage (doesn't allow resize under minimum size) titleLabel.setMinimumSize(new Dimension(30, titleLabel.getPreferredSize().height)); } /** Installs the default background of the title bar */ protected void installBackground(){ titleBar.setBackground(notSelectedTitleColor); } /** configure the title bar buttons */ protected void installButtons(){ JButton closeButton = titleBar.getCloseButton(); JButton dockButton = titleBar.getHideOrDockButton(); JButton maximizeButton = titleBar.getMaximizeOrRestoreButton(); JButton floatButton = titleBar.getFloatButton(); Insets buttonMargin = new Insets(0, 2, 0, 2); //todo put this in UI closeButton.setMargin(buttonMargin); dockButton.setMargin(buttonMargin); maximizeButton.setMargin(buttonMargin); floatButton.setMargin(buttonMargin); dockButton.setRolloverEnabled(true); dockButton.setBorderPainted(false); dockButton.setFocusable(false); dockButton.setContentAreaFilled(false); closeButton.setRolloverEnabled(true); closeButton.setBorderPainted(false); closeButton.setFocusable(false); closeButton.setContentAreaFilled(false); maximizeButton.setRolloverEnabled(true); maximizeButton.setBorderPainted(false); maximizeButton.setFocusable(false); maximizeButton.setContentAreaFilled(false); floatButton.setRolloverEnabled(true); floatButton.setBorderPainted(false); floatButton.setFocusable(false); floatButton.setContentAreaFilled(false); } /** Listen to property changes in the DockKey or the title bar */ public void propertyChange(PropertyChangeEvent e){ String pName = e.getPropertyName(); //System.out.println("property change " + pName); if (pName.equals("dockable")){ Dockable old = (Dockable)e.getOldValue(); if (old != null){ old.getDockKey().removePropertyChangeListener(this); } Dockable newDockable = ((Dockable)e.getNewValue()); if (newDockable != null){ configureButtons(titleBar); newDockable.getDockKey().addPropertyChangeListener(this); } } else if (pName.equals(DockKey.PROPERTY_AUTOHIDEABLE)){ boolean isAutoHideable = ((Boolean)e.getNewValue()).booleanValue(); boolean isMaximized = titleBar.getDockable() .getDockKey().getDockableState() == DockableState.STATE_MAXIMIZED; if (isAutoHideable){ if (! isMaximized){ titleBar.getHideOrDockButton().setVisible(true); configureHideButton(titleBar.getHideOrDockButton()); } } else { titleBar.getHideOrDockButton().setVisible(false); } } else if (pName.equals(DockKey.PROPERTY_MAXIMIZABLE)){ boolean isMaximizeable = ((Boolean)e.getNewValue()).booleanValue(); boolean isHidden = titleBar.getDockable() .getDockKey().getDockableState() == DockableState.STATE_HIDDEN; if (isMaximizeable){ if (! isHidden){ titleBar.getMaximizeOrRestoreButton().setVisible(true); configureMaximizeButton(titleBar.getMaximizeOrRestoreButton()); } } else { titleBar.getMaximizeOrRestoreButton().setVisible(false); } } else if (pName.equals(DockKey.PROPERTY_CLOSEABLE)) { boolean isCloseable = ((Boolean)e.getNewValue()).booleanValue(); boolean isMaximized = titleBar.getDockable() .getDockKey().getDockableState() == DockableState.STATE_MAXIMIZED; if (isCloseable){ if (! isMaximized){ titleBar.getCloseButton().setVisible(true); configureCloseButton(titleBar.getCloseButton()); } } else { titleBar.getCloseButton().setVisible(false); } } else if (pName.equals(DockKey.PROPERTY_FLOATABLE)) { boolean isFloatable = ((Boolean)e.getNewValue()).booleanValue(); boolean isMaximized = titleBar.getDockable() .getDockKey().getDockableState() == DockableState.STATE_MAXIMIZED; if (isFloatable){ if (! isMaximized){ titleBar.getFloatButton().setVisible(true); configureFloatButton(titleBar.getFloatButton()); } } else { titleBar.getFloatButton().setVisible(false); } } else if (pName.equals(DockKey.PROPERTY_DOCKABLE_STATE)){ configureButtons(titleBar); } else if (pName.equals("active")){ boolean isActive = ((Boolean)e.getNewValue()).booleanValue(); if (isActive) { titleBar.getTitleLabel().setForeground(selectedTextColor); titleBar.setBackground(selectedTitleColor); } else { titleBar.getTitleLabel().setForeground(notSelectedTextColor); titleBar.setBackground(notSelectedTitleColor); } titleBar.repaint(); } else if (pName.equals("titlebar.notification")){ boolean notification = ((Boolean)e.getNewValue()).booleanValue(); if (notification) { titleBar.setBackground(UIManager.getColor("DockingDesktop.notificationColor")); titleBar.setOpaque(true); } else { if (titleBar.isActive()) { titleBar.setBackground(selectedTitleColor); } else { titleBar.setBackground(notSelectedTitleColor); } titleBar.setOpaque(false); } titleBar.repaint(); } else if (pName.equals(DockKey.PROPERTY_NAME)){ titleBar.repaint(); } else if (pName.equals("clientProperty.visibleTitleBar")){ // 2006/12/01 boolean v = Boolean.TRUE.equals(e.getNewValue()); titleBar.setVisible(v); } } /** Update the buttons to track state changes (for example, the maximize button can become "restore" * when the view is maximized. */ protected void configureButtons(DockViewTitleBar tb){ DockKey key = tb.getDockable().getDockKey(); int state = key.getDockableState(); JButton closeButton = titleBar.getCloseButton(); JButton maxBtn = titleBar.getMaximizeOrRestoreButton(); JButton hideBtn = titleBar.getHideOrDockButton(); JButton floatBtn = titleBar.getFloatButton(); switch (state){ case DockableState.STATE_DOCKED: if (key.isCloseEnabled() && isCloseButtonDisplayed){ closeButton.setVisible(true); configureCloseButton(closeButton); } else { closeButton.setVisible(false); } if (key.isMaximizeEnabled() && isMaximizeButtonDisplayed){ maxBtn.setVisible(true); configureMaximizeButton(maxBtn); } else { maxBtn.setVisible(false); } boolean isChildOfMaximizedContainer = false; DockingDesktop desk = titleBar.getDesktop(); if (desk != null){ Dockable max = desk.getMaximizedDockable(); if (max != null && max.getComponent().getParent().isAncestorOf(titleBar)){ isChildOfMaximizedContainer = true; } } if (key.isAutoHideEnabled() && isHideButtonDisplayed && ! isChildOfMaximizedContainer){ hideBtn.setVisible(true); configureHideButton(hideBtn); } else { hideBtn.setVisible(false); } if (key.isFloatEnabled() && isFloatButtonDisplayed && !isChildOfMaximizedContainer){ floatBtn.setVisible(true); configureFloatButton(floatBtn); } else { floatBtn.setVisible(false); } titleBar.revalidate(); break; case DockableState.STATE_HIDDEN: if (key.isCloseEnabled() && isCloseButtonDisplayed){ closeButton.setVisible(true); configureCloseButton(closeButton); } else { closeButton.setVisible(false); } // maximize not allowed when in autohide mode maxBtn.setVisible(false); boolean isChildOfCompound = DockingUtilities.isChildOfCompoundDockable(tb.getDockable()); // idem for float if (key.isFloatEnabled() && isFloatButtonDisplayed && !isChildOfCompound){ floatBtn.setVisible(true); configureFloatButton(floatBtn); } else { floatBtn.setVisible(false); } // hide becomes dock if (isChildOfCompound){ //tb.getParent().getParent() instanceof AutoHideExpandPanel // V2.1 : only when not nested hideBtn.setVisible(false); } else { if (isDockButtonDisplayed && key.isAutoHideEnabled()){ // 2007/01/08 hideBtn.setVisible(true); configureDockButton(hideBtn); } else { hideBtn.setVisible(false); } } titleBar.revalidate(); break; case DockableState.STATE_MAXIMIZED: closeButton.setVisible(false); floatBtn.setVisible(false); // maxBtn becomes restore if (isRestoreButtonDisplayed){ configureRestoreButton(maxBtn); maxBtn.setVisible(true); } else { maxBtn.setVisible(false); } hideBtn.setVisible(false); titleBar.revalidate(); break; case DockableState.STATE_FLOATING: closeButton.setVisible(false); maxBtn.setVisible(false); hideBtn.setVisible(false); if (DockingUtilities.isChildOfCompoundDockable(tb.getDockable())){ // cannot attach a compound dockable directly floatBtn.setVisible(false); } else { floatBtn.setVisible(isAttachButtonDisplayed); configureAttachButton(floatBtn); } break; default : // not interesting } } /** installs the icons and tooltip suitable for a close button */ protected void configureCloseButton(JButton btn){ btn.setIcon(closeIcon); btn.setRolloverIcon(closeIconRollover); btn.setPressedIcon(closeIconPressed); btn.setRolloverSelectedIcon(closeIconRollover); btn.setToolTipText(CLOSE_TEXT); } /** installs the icons and tooltip suitable for a maximize button */ protected void configureMaximizeButton(JButton btn){ btn.setIcon(maximizeIcon); btn.setRolloverIcon(maximizeIconRollover); btn.setPressedIcon(maximizeIconPressed); btn.setRolloverSelectedIcon(maximizeIconRollover); btn.setToolTipText(MAXIMIZE_TEXT); } /** installs the icons and tooltip suitable for a restore button. */ protected void configureRestoreButton(JButton btn){ btn.setIcon(restoreIcon); btn.setRolloverIcon(restoreIconRollover); btn.setPressedIcon(restoreIconPressed); btn.setRolloverSelectedIcon(restoreIconRollover); btn.setToolTipText(RESTORE_TEXT); } /** installs the icons and tooltip suitable for a hide button */ protected void configureHideButton(JButton btn){ btn.setIcon(hideIcon); btn.setRolloverIcon(hideIconRollover); btn.setPressedIcon(hideIconPressed); btn.setRolloverSelectedIcon(hideIconRollover); btn.setToolTipText(ICONIFY_TEXT); } /** installs the icons and tooltip suitable for a dock button */ protected void configureDockButton(JButton btn){ btn.setIcon(dockIcon); btn.setRolloverIcon(dockIconRollover); btn.setPressedIcon(dockIconPressed); btn.setRolloverSelectedIcon(dockIconRollover); btn.setToolTipText(RESTORE_TEXT); } /** installs the icons and tooltip suitable for a float button */ protected void configureFloatButton(JButton btn){ btn.setIcon(floatIcon); btn.setRolloverIcon(floatIconRollover); btn.setPressedIcon(floatIconPressed); btn.setRolloverSelectedIcon(floatIconRollover); btn.setToolTipText(FLOAT_TEXT); } /** installs the icons and tooltip suitable for an attach button */ protected void configureAttachButton(JButton btn){ btn.setIcon(attachIcon); btn.setRolloverIcon(attachIconRollover); btn.setPressedIcon(attachIconPressed); btn.setRolloverSelectedIcon(attachIconRollover); btn.setToolTipText(ATTACH_TEXT); } /** installs the border of the title bar */ protected void installTitleBorder(JComponent c){ Border b = UIManager.getBorder("DockViewTitleBar.border"); c.setBorder(b); } /** uninstalls the icons and tooltip suitable for a close button */ protected void uninstallTitleBorder(JComponent c){ c.setBorder(null); } /** Custom title bar painting : uses a gradient from the background color * to the control highlight color. */ public void paint(Graphics g, JComponent c){ DockViewTitleBar tb = (DockViewTitleBar)c; if (useCustomPaint) { Graphics2D g2 = (Graphics2D) g.create(); g2.setColor(panelColor); g2.fillRect(0, 0, tb.getWidth(), tb.getHeight()); // emptyborder doesnt repaint Insets i = tb.getInsets(); g2.setColor(tb.getBackground()); Rectangle r = tb.getTitleLabel().getBounds(); int w = r.x + r.width; g2.fillRect(i.left, i.top, w, tb.getHeight() - i.top - i.bottom); // gradient paint after the label text (to ensure readeability) if (tb.isActive()) { g2.setPaint(new GradientPaint(i.left + w, 0, tb.getBackground(), tb.getWidth(), 0, highlight)); } else { g2.setPaint(new GradientPaint(i.left + w, 0, tb.getBackground(), tb.getWidth(), 0, highlight)); //panelColor)); } g2.fillRect(i.left + w, i.top, tb.getWidth() - w - i.left - i.right, tb.getHeight() - i.top - i.bottom); g2.dispose(); } super.paint(g, c); } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/ui/DockViewUI.java0000644000175000017500000001632710573516350025500 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking.ui; import com.vlsolutions.swing.docking.DockView; import com.vlsolutions.swing.docking.ShadowBorder; import com.vlsolutions.swing.docking.SplitContainer; import com.vlsolutions.swing.docking.TabbedDockableContainer; import java.awt.Color; import java.awt.Container; import javax.swing.BorderFactory; import javax.swing.JComponent; import javax.swing.UIManager; import javax.swing.border.Border; import javax.swing.event.AncestorEvent; import javax.swing.event.AncestorListener; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.PanelUI; /** This is the UI delegate for the DockView class. * *

Default behaviour in to install a shadow border on the dockview, * but this can be replaced by overriding the 3 installXXXDockableBorder methods. * * @author Lilian Chamontin, VLSolutions * * @since 2.0 */ public class DockViewUI extends PanelUI { /** Ancestor listener used to install different borders depending on the usage * of the dock view (docked, maximized, tabbed). */ protected ViewAncestorListener ancestorListener = new ViewAncestorListener(); private static DockViewUI instance = new DockViewUI(); public DockViewUI() { } public static ComponentUI createUI(JComponent c) { return instance; } public void installUI(JComponent c) { super.installUI(c); c.addAncestorListener(ancestorListener); } public void uninstallUI(JComponent c){ super.uninstallUI(c); c.removeAncestorListener(ancestorListener); } /** Installs a border when the DockView target is a SingleDockableContainer * (not nested in a tabbed container ) * *

default is a shadowed border. */ protected void installSingleDockableBorder(DockView v){ Border b = UIManager.getBorder("DockView.singleDockableBorder"); v.setBorder(b); } /** Installs a border when the DockView target is included in a TabbedDockableContainer. * *

Default is a shadow border without top and left shadows * */ protected void installTabbedDockableBorder(DockView v){ Border b = UIManager.getBorder("DockView.tabbedDockableBorder"); v.setBorder(b); } /** Installs a border when the DockView target is unique on the desktop (mamimized, or alone) * *

Default is a shadow border without top and left shadows * */ protected void installMaximizedDockableBorder(DockView v){ Border b = UIManager.getBorder("DockView.maximizedDockableBorder"); v.setBorder(b); } class ViewAncestorListener implements AncestorListener { public void ancestorAdded(AncestorEvent ancestorEvent) { DockView v = (DockView)ancestorEvent.getComponent(); Container parent = v.getParent(); if (parent instanceof TabbedDockableContainer){ installTabbedDockableBorder(v); } else if (parent instanceof SplitContainer){ installSingleDockableBorder(v); } else { installMaximizedDockableBorder(v); } } public void ancestorMoved(AncestorEvent ancestorEvent) { } public void ancestorRemoved(AncestorEvent ancestorEvent) { } } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/ui/DockingSplitPaneUI.java0000644000175000017500000002105210573516350027152 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking.ui; import com.vlsolutions.swing.docking.DockingPreferences; import javax.swing.plaf.basic.*; import javax.swing.*; import javax.swing.plaf.*; import java.awt.*; import java.awt.image.*; /** A specific UI for removing border effects of the JSplitPanes used for docking. * * @author Lilian Chamontin, vlsolutions. * @version 1.0 * */ public class DockingSplitPaneUI extends BasicSplitPaneUI{ Color shadow = UIManager.getColor("controlShadow"); Color highlight = UIManager.getColor("controlLtHighlight"); TexturePaint tp = null; private static boolean drawDelimitors = UIManager.getBoolean("SplitContainer.drawDotsDelimitors"); private static boolean useCustomImages = UIManager.getBoolean("SplitContainer.useCustomImages"); private static BufferedImage horizontalImage = (BufferedImage) UIManager.get("SplitContainer.hImage"); private static BufferedImage verticalImage = (BufferedImage) UIManager.get("SplitContainer.vImage"); private static int dividerSize = UIManager.getInt("SplitContainer.dividerSize"); public DockingSplitPaneUI() { } /** if true, the UI will paint shadowed dots along the split pane divider, * if false, the divider will remain empty. Default is false * @deprecated use UIManager.put("SplitContainer.drawDotsDelimitors", Boolean) instead */ public static void setDrawDelimitors(boolean draw){ drawDelimitors = draw; } /** * Creates a new DockingSplitPaneUI instance */ public static ComponentUI createUI(JComponent x) { return new DockingSplitPaneUI(); } public void installUI(JComponent comp){ super.installUI(comp); ((JSplitPane)comp).setDividerSize(dividerSize); } protected void installDefaults(){ super.installDefaults(); divider.setBorder(null); } /** * Creates the default divider. */ public BasicSplitPaneDivider createDefaultDivider() { DockingSplitPaneDivider bd = new DockingSplitPaneDivider(this); return bd; } class DockingSplitPaneDivider extends BasicSplitPaneDivider { DockingSplitPaneDivider(BasicSplitPaneUI ui){ super(ui); } public void paint(Graphics g) { Dimension size = getSize(); Color bgColor = getBackground(); if (bgColor != null) { g.setColor(bgColor); g.fillRect(0, 0, size.width, size.height); } if (useCustomImages){ Graphics2D g2 = (Graphics2D) g.create(); BufferedImage image = getOrientation() == JSplitPane.HORIZONTAL_SPLIT ? verticalImage : horizontalImage; int width = image.getWidth(); int height = image.getHeight(); // Create a texture paint from the buffered image Rectangle r = new Rectangle(0, 0, width, height); if (tp == null){ tp = new TexturePaint(image, r); } if (getOrientation() == JSplitPane.HORIZONTAL_SPLIT) { g2.setPaint(tp); g2.fillRect(size.width / 2 - width/2, 0, width, size.height); } else { g2.setPaint(tp); g2.fillRect(0, size.height / 2 - height/2, size.width, height); } } else if (drawDelimitors){ // special case : custom integrated dots delimitors if (tp == null) { // Create a buffered image texture patch of size 5x5 BufferedImage bi = new BufferedImage(4, 4, BufferedImage.TYPE_INT_RGB); Graphics2D big = bi.createGraphics(); // Render into the BufferedImage graphics to create the texture big.setColor(getBackground()); big.fillRect(0, 0, 4, 4); big.setColor(highlight); big.fillRect(1, 1, 1, 1); big.setColor(shadow); big.fillRect(2, 2, 1, 1); // Create a texture paint from the buffered image Rectangle r = new Rectangle(0, 0, 4, 4); tp = new TexturePaint(bi, r); big.dispose(); } // g.setColor(shadow); Graphics2D g2 = (Graphics2D) g.create(); // Add the texture paint to the graphics context. g2.setPaint(tp); if (getOrientation() == JSplitPane.HORIZONTAL_SPLIT) { g2.fillRect(size.width / 2 - 2, 0, 4, size.height); } else { g2.fillRect(0, size.height / 2 - 2, size.width, 4); } } //paintDragRectangle(g); super.paint(g); } } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/ui/DockingUISettings.java0000644000175000017500000010746110573516350027064 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking.ui; import com.vlsolutions.swing.toolbars.ToolBarPanelBorder; import java.awt.Color; import java.awt.Toolkit; import java.awt.event.KeyEvent; import javax.swing.BorderFactory; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.KeyStroke; import javax.swing.SwingConstants; import javax.swing.UIManager; import javax.swing.border.Border; /** Central class to manage Look and feel settings for the docking framework. *

* There are two ways of modifying the look and feel of the docking framework : *

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
UI property type effect
DockView.singleDockableBorder Border border used when the DockView is docked alone (not in a tab)
DockView.tabbedDockableBorder Border border used when the DockView is contained in a tabbed pane
DockView.maximizedDockableBorder Border border used when the DockView is maxmized
AutoHideButtonUI class name UI delegate for the AutoHideButton
AutoHideButtonPanelUI class name UI delegate for the AutoHideButtonPanel
AutoHideExpandPanelUI class name UI delegate for the AutoHideExpandPanel
AutoHideButton.expandBorderTop Border Border of the autohide button when it is on top of the desktop
AutoHideButton.expandBorderBottom Border Border of the autohide button when it is at bottom of the desktop
AutoHideButton.expandBorderLeft Border Border of the autohide button when it is on the left of the desktop
AutoHideButton.expandBorderRight Border Border of the autohide button when it is on the right of the desktop
AutoHideButtonPanel.topBorder Border Border of the AutoHideButtonPanel when it is on top of the desktop
AutoHideButtonPanel.bottomBorder Border Border of the AutoHideButtonPanel when it is at bottom of the desktop
AutoHideButtonPanel.leftBorder Border Border of the AutoHideButtonPanel when it is on the left of the desktop
AutoHideButtonPanel.rightBorder Border Border of the AutoHideButtonPanel when it is on the right of the desktop
DockViewUI class name UI delegate for DockView
DetachedDockViewUI class name UI delegate for DetachedDockView
DockViewTitleBarUI class name UI delegate for DockViewTitleBar
DockViewTitleBar.height int Height of the title bars
DockViewTitleBar.closeButtonText String Text of the close button
DockViewTitleBar.minimizeButtonText String Text of the minimize (hide) button
DockViewTitleBar.maximizeButtonText String Text of the maximize button
DockViewTitleBar.restoreButtonText String Text of the restore button(opposite of maximize)
DockViewTitleBar.floatButtonText String Text of the float button (detach)
DockViewTitleBar.attachButtonText String Text of the attach button(opposite of float)
DockViewTitleBar.titleFont Font Font used by the title bar
DockViewTitleBar.isCloseButtonDisplayed boolean display or not the close button in the title bar (still accessible from pop-up menu)
DockViewTitleBar.isHideButtonDisplayed boolean display or not the hide button in the title bar
DockViewTitleBar.isDockButtonDisplayed boolean display or not the dock button in the title bar
DockViewTitleBar.isMaximizeButtonDisplayed boolean display or not the maximize button in the title bar
DockViewTitleBar.isRestoreButtonDisplayed boolean display or not the restore button in the title bar
DockViewTitleBar.isFloatButtonDisplayed boolean display or not the float button in the title bar
DockViewTitleBar.isAttachButtonDisplayed boolean display or not the attach button in the title bar
DockViewTitleBar.border Border Border of the title bar
DockingSplitPaneUI class name UI delegate for SplitContainer component
SplitContainer.dividerSize int Divider size of the split panes
TabbedDockableContainer.tabPlacement int (SwingConstants.TOP / BOTTOM) Global tab style
DockTabbedPane.closeButtonText String Text for the close button in tab
DockTabbedPane.minimizeButtonText String Text for the minimize button in tab
DockTabbedPane.restoreButtonText String Text for the restore button in tab
DockTabbedPane.maximizeButtonText String Text for the maximize button in tab
DockTabbedPane.floatButtonText String Text for the float button in tab
DockTabbedPane.attachButtonText String Text for the attach button in tab (when floating)
TabbedContainer.requestFocusOnTabSelection boolean Automatically puts focus on the selected tabbed component (default false)
TabbedPane.otherIconsGap int Gap between text and close icon in closeable tab
TabbedPane.inBetweenOtherIconsGap int Gap between two icons
DockViewTitleBar.close Icon Icon for the close button
DockViewTitleBar.close.rollover Icon Icon for the close button
DockViewTitleBar.close.pressed Icon Icon for the close button
DockViewTitleBar.dock Icon Icon for the dock button
DockViewTitleBar.dock.rollover Icon Icon for the dock button
DockViewTitleBar.dock.pressed Icon Icon for the dock button
DockViewTitleBar.hide Icon Icon for the hide button
DockViewTitleBar.hide.rollover Icon Icon for the hide button
DockViewTitleBar.hide.pressed Icon Icon for the hide button
DockViewTitleBar.maximize Icon Icon for the maximize button
DockViewTitleBar.maximize.rollover Icon Icon for the maximize button
DockViewTitleBar.maximize.pressed Icon Icon for the maximize button
DockViewTitleBar.restore Icon Icon for the restore button
DockViewTitleBar.restore.rollover Icon Icon for the restore button
DockViewTitleBar.restore.pressed Icon Icon for the restore button
DockViewTitleBar.float Icon Icon for the float button
DockViewTitleBar.float.rollover Icon Icon for the float button
DockViewTitleBar.float.pressed Icon Icon for the float button
DockViewTitleBar.attach Icon Icon for the attach button
DockViewTitleBar.attach.rollover Icon Icon for the attach button
DockViewTitleBar.attach.pressed Icon Icon for the attach button
DockViewTitleBar.menu.close Icon Icon for the close button, in pop-up menu
DockViewTitleBar.menu.hide Icon Icon for the hide button, in pop-up menu
DockViewTitleBar.menu.maximize Icon Icon for the maximize button, in pop-up menu
DockViewTitleBar.menu.restore Icon Icon for the restore button, in pop-up menu
DockViewTitleBar.menu.dock Icon Icon for the dock button, in pop-up menu
DockViewTitleBar.menu.float Icon Icon for the float button, in pop-up menu
DockViewTitleBar.menu.attach Icon Icon for the attach button, in pop-up menu
DockTabbedPane.close Icon Icon for the close button, in tabs
DockTabbedPane.close.rollover Icon Icon for the close button, in tabs
DockTabbedPane.close.pressed Icon Icon for the close button, in tabs
DockTabbedPane.menu.close Icon Icon for the close button, in tab pop-up menu
DockTabbedPane.menu.hide Icon Icon for the hide button, in tab pop-up menu
DockTabbedPane.menu.maximize Icon Icon for the maximize button, in tab pop-up menu
DockTabbedPane.menu.float Icon Icon for the float button, in tab pop-up menu
DockTabbedPane.menu.attach Icon Icon for the attach button, in tab pop-up menu (when floating)
DockTabbedPane.menu.closeAll Icon Icon for the "close all" button, in tab pop-up menu
DockTabbedPane.menu.closeAllOther Icon Icon for the "close all other" button, in tab pop-up menu
DockingDesktop.closeActionAccelerator KeyStroke KeyStroke for close action (on selected dockable)
DockingDesktop.maximizeActionAccelerator KeyStroke KeyStroke for maximize/restore action (on selected dockable)
DockingDesktop.dockActionAccelerator KeyStroke KeyStroke for hide/dock action (on selected dockable)
DockingDesktop.floatActionAccelerator KeyStroke KeyStroke for float/attach action (on selected dockable)
DockingDesktop.notificationColor Color blinking color for notifications
DockingDesktop.notificationBlinkCount int maximum number of blinking for notifications
DragControler.stopDragCursor" ImageCursor image used when a drag and drop move is not allowed
DragControler.detachCursor" ImageCursor image used when a drag and drop move will detach the dockable
DragControler.dragCursor" ImageCursor image used when a drag and drop move is allowed(not leading to a detached dockable)
DragControler.swapDragCursor ImageCursor image used when doing a drag and drop with Ctrl key (hot swap)
DragControler.isDragAndDropEnabledBooleanGlobal switch to turn on/off drag and drop support in vldocking (default set to true)
DragControler.paintBackgroundUnderDragRectBooleanGlobal switch to turn on/off background painting under drag shapes (which can be slow on some linux distributions) (default set to true)
ToolBarGripperUI class name UI delegate for the toolbar "gripper"
ToolBarPanel.topBorder Border Border used when a toolbar in on the top of a container
ToolBarPanel.leftBorder Border Border used when a toolbar in on the left of a container
ToolBarPanel.bottomBorder Border Border used when a toolbar in at the bottom of a container
ToolBarPanel.rightBorder Border Border used when a toolbar in on the right of a container
FloatingDialog.dialogBorder Border Border used for the FloatingDialog
FloatingDialog.titleBorder Border Border used for the title (drag header) of the FloatingDialog
FloatingContainer.followParentWindow Boolean if true, the floating dialogs will follow the movements of their parent window on screen
FloatingContainer.paintDragShape Boolean if true, a drag outline shape will follow the mouse when dragging
* * @author Lilian Chamontin, VLSolutions */ public class DockingUISettings { static DockingUISettings instance = null; /** Field for installing settings only once */ protected boolean isSettingsInstalled = false; private Color shadow = UIManager.getColor("controlShadow"); private Color highlight = UIManager.getColor("controlLtHighlight"); private Color darkShadow = UIManager.getColor("controlDkShadow"); public DockingUISettings() { } /** returns the singleton instance used to store and install UI settings for the framework */ public static DockingUISettings getInstance(){ // give a chance to subclassers to install their own subclass instance if (instance == null){ instance = new DockingUISettings(); } return instance; } /** Allows replacement of the settings instance (used to override global look and feel * settings of the framework. *

* This method must be called before DockingDesktop is referenced, as the settings are statically * installed at that moment. */ public static void setInstance(DockingUISettings newInstance){ instance = newInstance; } /** Installs the UI settings. This is executed only once, and automatically called * at DockingDesktop class loading in case it was not called by the application. */ public void installUI(){ if (!isSettingsInstalled){ installAutoHideSettings(); installBorderSettings(); installDockViewSettings(); installDockViewTitleBarSettings(); installSplitContainerSettings(); installCloseableTabs(); installTabbedContainerSettings(); installIcons(); installAccelerators(); installDesktopSettings(); installFloatingSettings(); installToolBarSettings(); isSettingsInstalled = true; } } /** Allows updating of the ui after a look and feel change. *

* The Docking framework uses references of UI elements from this class to * install its UI according to the look and feel. When Laf is changed, and before * calling SwingUtilities.updateComponentTreeUI(topLevelComponent), invoke updateUI() in * order to reset everything. *

* Calling this method after SwingUtilities.updateComponentTreeUI(topLevelComponent) is * unspecified (some things will be updated, others not). */ public void updateUI(){ isSettingsInstalled = false; installUI(); } /** installs the borders */ public void installBorderSettings(){ // this is for the "flat style" (comment this line, or put a FALSE to revert to "shadow style" // flat style is the default (outside : empty 1 pix / inside : hightlight-top-left + shadow-bottom-right Border innerFlatSingleBorder = BorderFactory.createCompoundBorder( BorderFactory.createMatteBorder(1,1,0,0, highlight), BorderFactory.createMatteBorder(0,0,1,1, shadow)); Border flatSingleBorder = BorderFactory.createCompoundBorder( BorderFactory.createEmptyBorder(1,1,1,1), innerFlatSingleBorder); UIManager.put("DockView.singleDockableBorder", flatSingleBorder); UIManager.put("DockView.tabbedDockableBorder", null); UIManager.put("DockView.maximizedDockableBorder", null); } /** installs the autohide related properties */ public void installAutoHideSettings(){ UIManager.put("AutoHideButtonUI", "com.vlsolutions.swing.docking.ui.AutoHideButtonUI"); UIManager.put("AutoHideButtonPanelUI", "com.vlsolutions.swing.docking.ui.AutoHideButtonPanelUI"); UIManager.put("AutoHideExpandPanelUI", "com.vlsolutions.swing.docking.ui.AutoHideExpandPanelUI"); UIManager.put("AutoHideButton.expandBorderTop", BorderFactory.createCompoundBorder( BorderFactory.createCompoundBorder( BorderFactory.createMatteBorder(1, 1, 0, 1, shadow), BorderFactory.createMatteBorder(1, 1, 0, 1, highlight)), BorderFactory.createEmptyBorder(0, 6, 0, 6) )); UIManager.put("AutoHideButton.expandBorderBottom", BorderFactory.createCompoundBorder( BorderFactory.createCompoundBorder( BorderFactory.createMatteBorder(0, 1, 1, 1, shadow), BorderFactory.createMatteBorder(0, 1, 1, 1, highlight)), BorderFactory.createEmptyBorder(0, 6, 0, 6) )); UIManager.put("AutoHideButton.expandBorderLeft", BorderFactory.createCompoundBorder( BorderFactory.createCompoundBorder( BorderFactory.createMatteBorder(1, 1, 1, 0, shadow), BorderFactory.createMatteBorder(1, 1, 1, 0, highlight)), BorderFactory.createEmptyBorder(6, 0, 6, 0) )); UIManager.put("AutoHideButton.expandBorderRight", BorderFactory.createCompoundBorder( BorderFactory.createCompoundBorder( BorderFactory.createMatteBorder(1, 0, 1, 1, shadow), BorderFactory.createMatteBorder(1, 0, 1, 1, highlight)), BorderFactory.createEmptyBorder(6, 0, 6, 0) )); UIManager.put("AutoHideButtonPanel.topBorder", BorderFactory.createCompoundBorder( BorderFactory.createEmptyBorder(1,0,0,0), BorderFactory.createMatteBorder(0,0,1,0, shadow) )); UIManager.put("AutoHideButtonPanel.bottomBorder", BorderFactory.createCompoundBorder( BorderFactory.createEmptyBorder(0,0,1,0), BorderFactory.createMatteBorder(1,0,0,0, shadow) )); UIManager.put("AutoHideButtonPanel.leftBorder", BorderFactory.createCompoundBorder( BorderFactory.createEmptyBorder(0,1,0,1), BorderFactory.createMatteBorder(0,0,0,1, shadow) )); UIManager.put("AutoHideButtonPanel.rightBorder", BorderFactory.createCompoundBorder( BorderFactory.createEmptyBorder(0,1,0,1), BorderFactory.createMatteBorder(0,1,0,0, shadow) )); UIManager.put("AutoHideButton.font", UIManager.get("MenuItem.font")); //2006/01/23 } /** installs the DockView related properties */ public void installDockViewSettings(){ UIManager.put("DockViewUI", "com.vlsolutions.swing.docking.ui.DockViewUI"); UIManager.put("DetachedDockViewUI", "com.vlsolutions.swing.docking.ui.DetachedDockViewUI"); } /** installs the DockVieTitleBar related properties */ public void installDockViewTitleBarSettings(){ UIManager.put("DockViewTitleBarUI", "com.vlsolutions.swing.docking.ui.DockViewTitleBarUI"); UIManager.put("DockViewTitleBar.height", new Integer(20)); UIManager.put("DockViewTitleBar.closeButtonText", UIManager.getString("InternalFrameTitlePane.closeButtonText")); UIManager.put("DockViewTitleBar.minimizeButtonText", UIManager.getString("InternalFrameTitlePane.minimizeButtonText")); UIManager.put("DockViewTitleBar.restoreButtonText", UIManager.getString("InternalFrameTitlePane.restoreButtonText")); UIManager.put("DockViewTitleBar.maximizeButtonText", UIManager.getString("InternalFrameTitlePane.maximizeButtonText")); UIManager.put("DockViewTitleBar.floatButtonText", "Detach"); UIManager.put("DockViewTitleBar.attachButtonText", "Attach"); // font to be used in the title bar UIManager.put("DockViewTitleBar.titleFont", UIManager.get("InternalFrame.titleFont")); // are buttons displayed or just accessible from the contextual menu ? // setting one of these flags to false hide the button from the title bar // setting to true not necessarily shows the button, as it then depends // on the DockKey allowed states. UIManager.put("DockViewTitleBar.isCloseButtonDisplayed", Boolean.TRUE); UIManager.put("DockViewTitleBar.isHideButtonDisplayed", Boolean.TRUE); UIManager.put("DockViewTitleBar.isDockButtonDisplayed", Boolean.TRUE); UIManager.put("DockViewTitleBar.isMaximizeButtonDisplayed", Boolean.TRUE); UIManager.put("DockViewTitleBar.isRestoreButtonDisplayed", Boolean.TRUE); UIManager.put("DockViewTitleBar.isFloatButtonDisplayed", Boolean.TRUE); UIManager.put("DockViewTitleBar.isAttachButtonDisplayed", Boolean.TRUE); UIManager.put("DockViewTitleBar.border", BorderFactory.createMatteBorder(0, 0, 1, 0, shadow)); } /** installs the splitpanes related properties */ public void installSplitContainerSettings(){ UIManager.put("DockingSplitPaneUI", "com.vlsolutions.swing.docking.ui.DockingSplitPaneUI"); UIManager.put("SplitContainer.dividerSize", new Integer(4)); } /** installs the tabbed pane related properties */ public void installTabbedContainerSettings(){ final String prefix = "/com/vlsolutions/swing/docking/"; UIManager.put("TabbedDockableContainer.tabPlacement", new Integer(SwingConstants.TOP)); UIManager.put("DockTabbedPane.closeButtonText", UIManager.getString("InternalFrameTitlePane.closeButtonText")); UIManager.put("DockTabbedPane.minimizeButtonText", UIManager.getString("InternalFrameTitlePane.minimizeButtonText")); UIManager.put("DockTabbedPane.restoreButtonText", UIManager.getString("InternalFrameTitlePane.restoreButtonText")); UIManager.put("DockTabbedPane.maximizeButtonText", UIManager.getString("InternalFrameTitlePane.maximizeButtonText")); UIManager.put("DockTabbedPane.floatButtonText", "Detach"); UIManager.put("DockTabbedPane.attachButtonText", "Attach");//2005/10/07 UIManager.put("JTabbedPaneSmartIcon.font", UIManager.getFont("TabbedPane.font")); //2006/01/23 // set to true to set focus directly into a tabbed component when it becomes // selected UIManager.put("TabbedContainer.requestFocusOnTabSelection", Boolean.FALSE); } /** installs the closable tabs properties */ public void installCloseableTabs(){ // this one is already provided by the look and feel // UIManager.put("TabbedPane.textIconGap", new Integer(4)); UIManager.put("TabbedPane.otherIconsGap", new Integer(8)); UIManager.put("TabbedPane.inBetweenOtherIconsGap", new Integer(4)); UIManager.put("TabbedPane.alternateTabIcons", Boolean.FALSE); } /** installs icons used by the framework */ public void installIcons(){ final String prefix = "/com/vlsolutions/swing/docking/"; Icon closeIcon = new ImageIcon(getClass().getResource(prefix + "close16v2.png")); Icon closeRolloverIcon = new ImageIcon(getClass().getResource(prefix + "close16v2rollover.png")); Icon closePressedIcon = new ImageIcon(getClass().getResource(prefix + "close16v2pressed.png")); Icon closeTabIcon = new ImageIcon(getClass().getResource(prefix + "close16tab.png")); Icon closeTabRolloverIcon = new ImageIcon(getClass().getResource(prefix + "close16tabRollover.png")); Icon closeTabPressedIcon = new ImageIcon(getClass().getResource(prefix + "close16tabPressed.png")); Icon hideIcon = new ImageIcon(getClass().getResource(prefix + "hide16v2.png")); Icon hideRolloverIcon = new ImageIcon(getClass().getResource(prefix + "hide16v2rollover.png")); Icon maximizeIcon = new ImageIcon(getClass().getResource(prefix + "maximize16v2.png")); Icon maximizeRolloverIcon = new ImageIcon(getClass().getResource(prefix + "maximize16v2rollover.png")); Icon restoreIcon = new ImageIcon(getClass().getResource(prefix + "restore16v2.png")); Icon restoreRolloverIcon = new ImageIcon(getClass().getResource(prefix + "restore16v2rollover.png")); Icon dockRolloverIcon = new ImageIcon(getClass().getResource(prefix + "dock16v2rollover.png")); Icon floatIcon = new ImageIcon(getClass().getResource(prefix + "float16v2.png")); Icon floatRolloverIcon = new ImageIcon(getClass().getResource(prefix + "float16v2rollover.png")); Icon floatPressedIcon = new ImageIcon(getClass().getResource(prefix + "float16v2pressed.png")); Icon attachIcon = new ImageIcon(getClass().getResource(prefix + "attach16v2.png")); Icon attachRolloverIcon = new ImageIcon(getClass().getResource(prefix + "attach16v2rollover.png")); Icon attachPressedIcon = new ImageIcon(getClass().getResource(prefix + "attach16v2pressed.png")); UIManager.put("DockViewTitleBar.close", closeIcon); UIManager.put("DockViewTitleBar.close.rollover", closeRolloverIcon); UIManager.put("DockViewTitleBar.close.pressed", closePressedIcon); UIManager.put("DockViewTitleBar.dock", new ImageIcon(getClass().getResource(prefix + "dock16v2.png"))); UIManager.put("DockViewTitleBar.dock.rollover", dockRolloverIcon); UIManager.put("DockViewTitleBar.dock.pressed", new ImageIcon(getClass().getResource(prefix + "dock16v2pressed.png"))); UIManager.put("DockViewTitleBar.hide", hideIcon); UIManager.put("DockViewTitleBar.hide.rollover", hideRolloverIcon); UIManager.put("DockViewTitleBar.hide.pressed", new ImageIcon(getClass().getResource(prefix + "hide16v2pressed.png"))); UIManager.put("DockViewTitleBar.maximize", maximizeIcon); UIManager.put("DockViewTitleBar.maximize.pressed", new ImageIcon(getClass().getResource(prefix + "maximize16v2pressed.png"))); UIManager.put("DockViewTitleBar.maximize.rollover", maximizeRolloverIcon); UIManager.put("DockViewTitleBar.restore", restoreIcon); UIManager.put("DockViewTitleBar.restore.pressed", new ImageIcon(getClass().getResource(prefix + "restore16v2pressed.png"))); UIManager.put("DockViewTitleBar.restore.rollover", restoreRolloverIcon); UIManager.put("DockViewTitleBar.float", floatIcon); UIManager.put("DockViewTitleBar.float.rollover", floatRolloverIcon); UIManager.put("DockViewTitleBar.float.pressed", floatPressedIcon); UIManager.put("DockViewTitleBar.attach", attachIcon); UIManager.put("DockViewTitleBar.attach.rollover", attachRolloverIcon); UIManager.put("DockViewTitleBar.attach.pressed", attachPressedIcon); UIManager.put("DockViewTitleBar.menu.close", closeRolloverIcon); UIManager.put("DockViewTitleBar.menu.hide", hideRolloverIcon); UIManager.put("DockViewTitleBar.menu.maximize", maximizeRolloverIcon); UIManager.put("DockViewTitleBar.menu.restore", restoreRolloverIcon); UIManager.put("DockViewTitleBar.menu.dock", dockRolloverIcon); UIManager.put("DockViewTitleBar.menu.float", floatRolloverIcon); UIManager.put("DockViewTitleBar.menu.attach", attachRolloverIcon); UIManager.put("DockTabbedPane.close", closeIcon); UIManager.put("DockTabbedPane.close.rollover", closeRolloverIcon); UIManager.put("DockTabbedPane.close.pressed", closePressedIcon); UIManager.put("DockTabbedPane.unselected_close", null); //2005/11/14 UIManager.put("DockTabbedPane.unselected_close.rollover", closeRolloverIcon); UIManager.put("DockTabbedPane.unselected_close.pressed", closePressedIcon); UIManager.put("DockTabbedPane.menu.close", closeRolloverIcon); UIManager.put("DockTabbedPane.menu.hide", hideRolloverIcon); UIManager.put("DockTabbedPane.menu.maximize", maximizeRolloverIcon); UIManager.put("DockTabbedPane.menu.float", floatRolloverIcon); UIManager.put("DockTabbedPane.closeAll", new ImageIcon(getClass().getResource(prefix + "closeAll16.png"))); UIManager.put("DockTabbedPane.closeAllOther", new ImageIcon(getClass().getResource(prefix + "closeAllOther16.png"))); UIManager.put("DockTabbedPane.menu.attach", attachRolloverIcon); //2005/10/07 } /** installs the eyboard shortcuts */ public void installAccelerators(){ int MENU_SHORTCUT_MASK = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); // this returns CTRL_MASK or META_MASK depending on the platform (win/mac os) UIManager.put("DockingDesktop.closeActionAccelerator", KeyStroke.getKeyStroke( KeyEvent.VK_F4, MENU_SHORTCUT_MASK)); // toggle maximize/restore UIManager.put("DockingDesktop.maximizeActionAccelerator", KeyStroke.getKeyStroke( KeyEvent.VK_ESCAPE, KeyEvent.SHIFT_MASK)); // toggle autohide/dock UIManager.put("DockingDesktop.dockActionAccelerator", KeyStroke.getKeyStroke( KeyEvent.VK_BACK_SPACE, MENU_SHORTCUT_MASK)); UIManager.put("DockingDesktop.floatActionAccelerator", KeyStroke.getKeyStroke( KeyEvent.VK_F5, MENU_SHORTCUT_MASK)); } /** installs the DockinDesktop related properties */ public void installDesktopSettings(){ UIManager.put("DockingDesktop.notificationColor", Color.ORANGE); UIManager.put("DockingDesktop.notificationBlinkCount", new Integer(5)); UIManager.put("DragControler.stopDragCursor", new ImageIcon( getClass().getResource("/com/vlsolutions/swing/docking/stopdragcursor.gif")).getImage()); UIManager.put("DragControler.detachCursor", new ImageIcon( getClass().getResource("/com/vlsolutions/swing/docking/detachCursor.png")).getImage()); UIManager.put("DragControler.dragCursor", new ImageIcon( getClass().getResource("/com/vlsolutions/swing/docking/dragcursor.gif")).getImage()); UIManager.put("DragControler.swapDragCursor", new ImageIcon( getClass().getResource("/com/vlsolutions/swing/docking/swapdragcursor.gif")).getImage()); UIManager.put("DragControler.isDragAndDropEnabled", Boolean.TRUE); UIManager.put("DragControler.paintBackgroundUnderDragRect", Boolean.FALSE); } /** installs the FloatingDialog related properties */ public void installFloatingSettings(){ // Border border = BorderFactory.createMatteBorder(1,1,1,1, darkShadow); // Border titleBorder = BorderFactory.createMatteBorder(0,0,1,0, highlight); Border border = null;//BorderFactory.createEmptyBorder(1,1,1,1); Border titleBorder = null;//BorderFactory.createMatteBorder(0,0,1,0, shadow); UIManager.put("FloatingDialog.dialogBorder", border); UIManager.put("FloatingDialog.titleBorder", titleBorder); UIManager.put("FloatingContainer.followParentWindow", Boolean.TRUE); UIManager.put("FloatingContainer.paintDragShape", Boolean.TRUE); } /** installs the toolbar related properties */ public void installToolBarSettings(){ UIManager.put("ToolBarGripperUI", "com.vlsolutions.swing.toolbars.ToolBarGripperUI"); // borders to use with toolbarpanels depending on their position UIManager.put("ToolBarPanel.topBorder", new ToolBarPanelBorder(ToolBarPanelBorder.TOP_PANEL)); UIManager.put("ToolBarPanel.leftBorder", new ToolBarPanelBorder(ToolBarPanelBorder.LEFT_PANEL)); UIManager.put("ToolBarPanel.bottomBorder", new ToolBarPanelBorder(ToolBarPanelBorder.BOTTOM_PANEL)); UIManager.put("ToolBarPanel.rightBorder", new ToolBarPanelBorder(ToolBarPanelBorder.RIGHT_PANEL)); } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/ui/package.html0000644000175000017500000000105710573516344025142 0ustar twernertwerner

UI Package of the docking framework.

This package contains classes related to UI management (look and feel classes).

Customizing the UI of the Docking Framework

Since Version 2.0, almost every visual property of the Docking Framework is stored with DockingUISettings in the form or UI properties.

There properties can be Fonts, Colors, Borders, or UI delegates class names.

The complete list of properties can be found in the DockingUISettings class. vldocking_2.1.4/src/com/vlsolutions/swing/docking/ws/0000755000175000017500000000000010573516350022667 5ustar twernertwernervldocking_2.1.4/src/com/vlsolutions/swing/docking/ws/WSDesktop.java0000644000175000017500000010763510573516350025431 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking.ws; import com.vlsolutions.swing.docking.AutoHidePolicy; import com.vlsolutions.swing.docking.DockableState; import com.vlsolutions.swing.docking.DockingConstants; import com.vlsolutions.swing.docking.RelativeDockablePosition; import com.vlsolutions.swing.docking.SplitContainer; import java.awt.Rectangle; import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import javax.swing.JSplitPane; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import org.xml.sax.SAXNotRecognizedException; /** A desktop part of a workpace. *

* Use this object to define the layout of a DockingDesktop. This layout can be applied later * to that desktop through the Workspace.apply(DockingContext ctx) method. *

* The API is a subset of the one of DockingDesktop : limited to layout building. * you can addDockable(), split(), createTab(), addHiddenDockable(), addFloatingDockable(), see these * method description for further information. *

* Node : WSDesktop doens't support layout updates : you should use it to build a layout, but not to * move dockables around. (if you add a dockable somewhere, don't add it elsewhere later as removal isn't * fully implemented). *

* In a WSDesktop, dockables are identified by a WSDockKey (a limited version of DockKey) : this is to allow * you to create workspaces with dockables that haven't been constructed yet (lazy loading). *

*Example : *

 *  Workspace w = new Workspace();
 *  WSDesktop desk = w.getDesktop(0); // gets the default (single) desktop
 * // define some dockable keys
 *  WSDockKey editorKey = new WSDockKey("editor");
 *  WSDockKey treeKey, tableKey, imgToolKey // other dockable keys
 *
 * // now define a workspace layout
 *  desk.addDockable(editorKey); // initial dockable
 *  desk.split(editorKey, treeKey, DockingConstants.SPLIT_LEFT, 0.5);  // splitted
 *  desk.split(treeKey, tableKey, DockingConstants.SPLIT_TOP, 0.7);  // tree is also splitted
 *
 *  desk.createTab(tableKey, imgToolsKey, 0);  // tableKey is transformed into a tabbed container
 * // and that's it
 * // ...
 * // later
 * //
 * DockingContext ctx = ... // your real desktop
 * w.apply(ctx); // applies the workspace to this desktop
 * // now the dektops are loaded as specified in the 'w' workspace
 *
* * @author Lilian Chamontin, VLSolutions * @since 2.1.2 */ public class WSDesktop { /** The name of this desktop (which must match the name of a real desktop if more than one desktops are used ) */ private String desktopName; /** root node for desktop (<=> DockingPanel) */ private TopLevelNode mainNode = new TopLevelNode(); /** Map of Nodes (key : WSDockKey, value : Node)*/ private HashMap nodesByKey = new HashMap(); /** 4 borders of this desktop */ private ArrayList [] borders = new ArrayList[4]; /** <=> floating windows */ private ArrayList floatingNodes = new ArrayList(); private WSDockKey maximizedDockable = null; /** groups of tabs (used to re-tab autohidden dockable)*/ protected HashMap tabbedGroups = new HashMap(); // / /** Constructs a WSDesktop with "default" as name */ public WSDesktop() { this("default"); } /** Constructs a WSDesktop with a given name */ public WSDesktop(String desktopName){ this.desktopName = desktopName; for (int i=0; i < borders.length; i++){ borders[i] = new ArrayList(); } } /** removes all information stored into this desktop, which becomes ready to * be reused. */ public void clear(){ mainNode = new TopLevelNode(); nodesByKey.clear(); for (int i=0; i < borders.length; i++){ borders[i].clear(); } floatingNodes.clear(); maximizedDockable = null; } /** Adds the first dockable to this desktop. This method will fail if called more than once */ public void addDockable(WSDockKey key){ if (mainNode.child != null){ throw new IllegalArgumentException("this workspace isn't empty"); } mainNode.setChild(new SingleDockableNode(key)); } /** Sets the maximized dockable of this desktop, (or null if no dockable maximized). *

* Don't forget that this dockable MUST ALSO BE in the DOCKED state (added to the desktop * in a split, tab or compound node) otherwise the missing restore information will cause * unwanted behaviour, or exceptions. */ public void setMaximizedDockable(WSDockKey max){ this.maximizedDockable = max; } private SingleDockableNode getNode(WSDockKey key){ return (SingleDockableNode) nodesByKey.get(key); } /** Splits a dockable (with a given split location) * * @param base the dockable to be splitted * @param newDockable the new dockable * @param split the orientation of split * @param splitLocation where the split divisor is (always relative from the top/left dockable, so * split(a, b, SPLIT_TOP, 0.1f) and split(a, b, SPLIT_BOTTOM, 0.1f) have the same dividor location (somewhere near * the top of the split). */ public void split(WSDockKey base, WSDockKey newDockable, DockingConstants.Split split, double splitLocation){ Node baseNode = getNode(base); if (baseNode == null){ throw new IllegalArgumentException("base dockable not found " + base); } SplitNode splitNode = new SplitNode(); replaceChild(baseNode.parent, baseNode, splitNode); switch(split.value()){ case DockingConstants.INT_SPLIT_TOP: splitNode.setTop(new SingleDockableNode(newDockable)); splitNode.setBottom(baseNode); splitNode.isHorizontal = false; break; case DockingConstants.INT_SPLIT_LEFT: splitNode.setLeft(new SingleDockableNode(newDockable)); splitNode.setRight(baseNode); splitNode.isHorizontal = true; break; case DockingConstants.INT_SPLIT_BOTTOM: splitNode.setBottom(new SingleDockableNode(newDockable)); splitNode.setTop(baseNode); splitNode.isHorizontal = false; break; case DockingConstants.INT_SPLIT_RIGHT: splitNode.setRight(new SingleDockableNode(newDockable)); splitNode.setLeft(baseNode); splitNode.isHorizontal = true; break; } splitNode.location = splitLocation; } /** Creates a tab containing baseTab and newTab (if baseTab is already into a Tab, then * newTab will just be added at the "order" position. */ public void createTab(WSDockKey baseTab, WSDockKey newTab, int order){ SingleDockableNode baseTabNode = getNode(baseTab); if (baseTabNode == null){ throw new IllegalArgumentException("base dockable not found " + baseTab); } if (baseTabNode.parent instanceof TabNode){ // already in a tab TabNode parent = (TabNode) baseTabNode.parent; parent.addTab(order, new SingleDockableNode(newTab)); } else { // replace parent by a tab TabNode gParent = new TabNode(); replaceChild(baseTabNode.parent, baseTabNode, gParent); gParent.addTab(0, baseTabNode); gParent.addTab(order, new SingleDockableNode(newTab)); } } /** Adds a dockable into a compound dockable */ public void addDockable(WSDockKey compoundDockable, WSDockKey childDockable){ SingleDockableNode node = getNode(compoundDockable); Node parent = node.parent; CompoundDockableNode cnode = new CompoundDockableNode(compoundDockable); replaceChild(parent, node, cnode); cnode.setNestedNode(new SingleDockableNode(childDockable)); } /** Adds a new dockable (and stores its return-to-docked position) */ public void addHiddenDockable(WSDockKey dockable, RelativeDockablePosition dockedPosition){ int zone; if (dockable.getAutoHideBorder() == null) { zone = AutoHidePolicy.getPolicy().getDefaultHideBorder().value(); } else { zone = dockable.getAutoHideBorder().value(); } ArrayList border = borders[zone]; border.add(new HiddenNode(new SingleDockableNode(dockable), dockedPosition)); } /** Adds a new floating dockable * * @param dockable the dockable to add as floating * @param windowRect rectangle defining the window (relative to screen) of the floating dockable * @param returnPosition where to put the dockable when returning to the desktop * */ public void setFloating(WSDockKey dockable, Rectangle windowRect, RelativeDockablePosition returnPosition){ FloatingNode f = new FloatingNode(new SingleDockableNode(dockable), windowRect, returnPosition); floatingNodes.add(f); } /** Returns the name of this desktop (which must match the name of a real desktop if more than one desktops are used ) */ public String getDesktopName() { return desktopName; } /** Updates the name of this workspace desktop */ public void setDesktopName(String name) { this.desktopName = name; } /** Package method : used to encode this desktop into an XML stream */ void writeDesktopNode(PrintWriter out) { out.println(""); out.println(""); if (mainNode.child != null){ xmlWriteComponent(mainNode.child, out); } if (maximizedDockable != null){ out.println(""); out.println(""); out.println(""); } out.println(""); for (int i = 0; i < borders.length; i++) { xmlWriteBorder(i, borders[i], out); } // finish with the floating dockables for (int i=0; i < floatingNodes.size(); i++){ FloatingNode f = (FloatingNode) floatingNodes.get(i); xmlWriteFloating(f, out); } // and the tab groups xmlWriteTabGroups(out); out.println(""); } private void xmlWriteComponent(Node node, PrintWriter out) { if (node instanceof SplitNode){ xmlWriteSplit((SplitNode) node, out); } else if (node instanceof TabNode){ xmlWriteTab((TabNode)node, out); } else if (node instanceof SingleDockableNode){ xmlWriteDockable((SingleDockableNode)node, out); } } private void xmlWriteSplit(SplitNode splitNode, PrintWriter out) { double location = splitNode.location; int orientation = splitNode.isHorizontal ? JSplitPane.HORIZONTAL_SPLIT : JSplitPane.VERTICAL_SPLIT; out.println(""); xmlWriteComponent(splitNode.getLeft(), out); xmlWriteComponent(splitNode.getRight(), out); out.println(""); } private void xmlWriteTab(TabNode tabNode, PrintWriter out) { out.println(""); for (int i = 0; i < tabNode.tabs.size(); i++) { xmlWriteDockable(tabNode.getTab(i), out); } out.println(""); } private void xmlWriteDockable(SingleDockableNode dockable, PrintWriter out) { boolean isCompound = dockable instanceof CompoundDockableNode; if (isCompound){ out.println(""); } else { out.println(""); } WSDockKey key = dockable.key; out.println(""); if (isCompound){ CompoundDockableNode d = (CompoundDockableNode)dockable; if (d.nestedNode != null){ // compound panels cannont have more than one child (split/tab/single) xmlWriteComponent(d.nestedNode, out); } } out.println(""); } private void xmlWriteBorder(int zone, ArrayList border, PrintWriter out) { if (border.size() > 0){ out.println(""); for (int i=0; i < border.size(); i++){ HiddenNode node = (HiddenNode) border.get(i); xmlWriteBorderDockable(node, out); } out.println(""); } } private void xmlWriteBorderDockable(HiddenNode node, PrintWriter out) { RelativeDockablePosition position = node.position; SingleDockableNode child = node.node; boolean isCompound = child instanceof CompoundDockableNode; if (isCompound){ out.println(""); } else { out.println(""); } WSDockKey key = child.key; out.println(""); out.println(""); if (isCompound){ CompoundDockableNode d = (CompoundDockableNode)child; if (d.nestedNode != null){ // compound panels cannont have more than one child (split/tab/single) xmlWriteComponent(d.nestedNode, out); } } out.println(""); } private void replaceChild(Node parent, Node child, Node newChild) { if (parent instanceof TopLevelNode){ TopLevelNode t = ((TopLevelNode)parent); if (t.child == child){ t.setChild(newChild); } else { throw new IllegalArgumentException("child not found in top level node " + child); } } else if (parent instanceof CompoundDockableNode){ CompoundDockableNode c = ((CompoundDockableNode)parent); if (c.nestedNode == child){ c.setNestedNode(newChild); } else { throw new IllegalArgumentException("child not found in compound " + child); } } else if (parent instanceof SplitNode){ SplitNode split = (SplitNode) parent; if (split.left == child){ split.setLeft(newChild); } else if (split.right == child){ split.setRight(newChild); } else { throw new IllegalArgumentException("child not found in split " + child); } } else if (parent instanceof TabNode){ TabNode tab = (TabNode) parent; for (int i=0; i < tab.tabs.size(); i++){ Node n = tab.getTab(i); if (n == child){ tab.replaceTab(i, (SingleDockableNode) newChild); break; } } throw new IllegalArgumentException("child not found in tabs " + child); } else if (parent instanceof HiddenNode){ HiddenNode h = (HiddenNode) parent; if (h.node == child){ h.setChild((SingleDockableNode) newChild); } else { throw new IllegalArgumentException("child not found in hidden dockable " + child); } } else if (parent instanceof FloatingNode){ FloatingNode f = (FloatingNode) parent; if (f.child == child){ f.setChild(newChild); } else { throw new IllegalArgumentException("child not found in floating dockable " + child); } } else { throw new IllegalArgumentException("wrong type for parent " + parent); } } private void xmlWriteFloating(FloatingNode node, PrintWriter out) { Rectangle r = node.windowRect; out.println(""); if (node.child instanceof TabNode){ TabNode tab = (TabNode) node.child; for (int i=0; i < tab.tabs.size(); i++){ SingleDockableNode n = tab.getTab(i); xmlWriteFloatingDockable(n, out, node.returnPosition); } } else { // single xmlWriteFloatingDockable((SingleDockableNode)node.child, out, node.returnPosition); } out.println(""); } private void xmlWriteFloatingDockable(SingleDockableNode dockable, PrintWriter out, RelativeDockablePosition returnPosition) { boolean isCompound = dockable instanceof CompoundDockableNode; if (isCompound){ out.println(""); } else { out.println(""); } WSDockKey key = dockable.key; out.println(""); out.println(""); out.println(""); // @todo : see how to implement that if (isCompound){ CompoundDockableNode d = (CompoundDockableNode)dockable; if (d.nestedNode != null){ // compound panels cannont have more than one child (split/tab/single) xmlWriteComponent(d.nestedNode, out); } } out.println(""); } private void xmlWriteTabGroups(PrintWriter out) { ArrayList uniqueGroups = new ArrayList(); ArrayList processedDockables = new ArrayList(); Iterator it = tabbedGroups.keySet().iterator(); while (it.hasNext()){ WSDockKey d = (WSDockKey) it.next(); if (! processedDockables.contains(d)){ processedDockables.add(d); LinkedList tabList = (LinkedList) tabbedGroups.get(d); Iterator listIt = tabList.iterator(); while (listIt.hasNext()){ WSDockKey d2 = (WSDockKey) listIt.next(); if (!processedDockables.contains(d2)){ processedDockables.add(d2); } } uniqueGroups.add(tabList); } } out.println(""); for (int i = 0; i < uniqueGroups.size(); i++) { out.println(""); LinkedList group = (LinkedList) uniqueGroups.get(i); Iterator listIt = group.iterator(); while (listIt.hasNext()) { WSDockKey d = (WSDockKey) listIt.next(); xmlWriteDockableTab(d, out); } out.println(""); } out.println(""); } private void xmlWriteDockableTab(WSDockKey key, PrintWriter out) { out.println(""); out.println(""); out.println(""); } void readDesktopNode(Element root) throws SAXNotRecognizedException, SAXException { NodeList children = root.getChildNodes(); for (int i = 0, len = children.getLength(); i < len; i++) { org.w3c.dom.Node child = children.item(i); xmlBuildRootNode(child); } } private void xmlBuildRootNode(org.w3c.dom.Node node) throws SAXNotRecognizedException, SAXException { if (node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE){ Element elt = (Element) node; String name = elt.getNodeName(); if (name.equals("DockingPanel")){ // only one child at most NodeList children = elt.getChildNodes(); for (int i = 0, len = children.getLength(); i < len; i++) { xmlBuildDockingPanelNode(elt.getChildNodes().item(i)); } } else if (name.equals("Border")){ int zone = Integer.parseInt(elt.getAttribute("zone")); NodeList children = elt.getElementsByTagName("Dockable"); for (int i = 0, len = children.getLength(); i < len; i++) { xmlBuildAutoHideNode(zone, (Element)children.item(i)); } } else if (name.equals("Floating")){ int x = Integer.parseInt(elt.getAttribute("x")); int y = Integer.parseInt(elt.getAttribute("y")); int width = Integer.parseInt(elt.getAttribute("width")); int height = Integer.parseInt(elt.getAttribute("height")); NodeList children = elt.getElementsByTagName("Dockable"); xmlBuildFloatingNode(children, new Rectangle(x, y, width, height)); //2005/10/10 /* for (int i = 0, len = children.getLength(); i < len; i++) { xmlBuildFloatingNode((Element)children.item(i), new Rectangle(x, y, width, height)); }*/ } else if (name.equals("TabGroups")){ NodeList children = elt.getElementsByTagName("TabGroup"); xmlBuildTabGroup(children); //2005/10/10 } else { throw new SAXNotRecognizedException(name); } } } private void xmlBuildDockingPanelNode(org.w3c.dom.Node node) throws SAXException { if (node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE){ Node child = xmlCreateComponent((Element) node, DockableState.STATE_DOCKED); if (node != null){ mainNode.setChild(child); } } } private Node xmlCreateComponent(Element elt, int dockableState) throws SAXException { if (elt.getNodeName().equals("Split")){ SplitNode split = xmlBuildSplitContainer(elt, dockableState); return split; } else if (elt.getNodeName().equals("Dockable")){ SingleDockableNode sdc = xmlGetDockable(elt); if (sdc instanceof CompoundDockableNode){ // check for children and build them xmlBuildCompoundDockable((CompoundDockableNode) sdc, elt, dockableState); } return sdc; } else if (elt.getNodeName().equals("TabbedDockable")){ TabNode tdc = xmlBuildTabbedDockableContainer(elt, dockableState); return tdc; } else if (elt.getNodeName().equals("MaximizedDockable")){ // this should be the last element from DockingPanel node SingleDockableNode sdc = xmlGetDockable(elt); setMaximizedDockable(sdc.key); return null; } else { throw new SAXNotRecognizedException(elt.getNodeName()); } } private SingleDockableNode xmlGetDockable(Element dockableElt) { Element key = (Element)dockableElt.getElementsByTagName("Key").item(0); String name = key.getAttribute("dockName"); WSDockKey wsKey = new WSDockKey(name); SingleDockableNode sdn = (SingleDockableNode) nodesByKey.get(wsKey); if (sdn == null){ String compound = dockableElt.getAttribute("compound"); if ("true".equals(compound)){ sdn = new CompoundDockableNode(wsKey); } else { sdn = new SingleDockableNode(wsKey); } } return sdn; } private void xmlBuildCompoundDockable(CompoundDockableNode cdn, Element elt, int dockableState) throws SAXException { /* a compound dockable can hold a sub dockable (or split/tabs) */ NodeList children = elt.getChildNodes(); for (int i = 0, len = children.getLength(); i < len; i++) { org.w3c.dom.Node node = children.item(i); if (node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE){ if (elt.getNodeName().equals("Key")){ // ignore : it's the key of the compound dockable } else { Node comp = xmlCreateComponent(elt, dockableState); cdn.nestedNode = comp; return; // no more than a single child } } } } private SplitNode xmlBuildSplitContainer(Element elt, int dockableState) throws SAXException { int orientation = Integer.parseInt(elt.getAttribute("orientation")); String loc = elt.getAttribute("location"); double location = 0.5; if (loc != null && !loc.equals("")){ location = Double.parseDouble(loc); } SplitNode split = new SplitNode(); split.isHorizontal = orientation == SplitContainer.HORIZONTAL_SPLIT; split.location = location; boolean left = true; for (int i = 0; i < elt.getChildNodes().getLength(); i++) { org.w3c.dom.Node child = elt.getChildNodes().item(i); if (child.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE){ Node comp = xmlCreateComponent((Element)child, dockableState); if (left){ split.setLeft(comp); left = false; } else { split.setRight(comp); } } } return split; } private TabNode xmlBuildTabbedDockableContainer(Element elt, int dockableState) throws SAXException { TabNode tdc = new TabNode(); int index = 0; for (int i = 0; i < elt.getChildNodes().getLength(); i++) { org.w3c.dom.Node child = elt.getChildNodes().item(i); if (child.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE){ SingleDockableNode sdn = xmlGetDockable((Element) child); tdc.addTab(index++, sdn); // we don't update the tab group as it is done in a separate pass (xmlBuildTabGroups()) if (sdn instanceof CompoundDockableNode){ // check for children and build them is needed xmlBuildCompoundDockable((CompoundDockableNode) sdn, (Element) child, dockableState); } } } return tdc; } private void xmlBuildAutoHideNode(int zone, Element dockableElt) throws SAXException { Element hideElt = (Element)dockableElt.getElementsByTagName("RelativePosition").item(0); float x = Float.parseFloat(hideElt.getAttribute("x")); float y = Float.parseFloat(hideElt.getAttribute("y")); float w = Float.parseFloat(hideElt.getAttribute("w")); float h = Float.parseFloat(hideElt.getAttribute("h")); RelativeDockablePosition position = new RelativeDockablePosition(x, y, w, h); SingleDockableNode dockable = xmlGetDockable(dockableElt); borders[zone].add(new HiddenNode(dockable, position)); if (dockable instanceof CompoundDockableNode){ // check for children and build them xmlBuildCompoundDockable((CompoundDockableNode) dockable, dockableElt, DockableState.STATE_HIDDEN); } } private void xmlBuildFloatingNode(NodeList dockables, Rectangle rectangle) throws SAXException { // @todo not optimal.. we should refactor it oustide this method FloatingNode floating = null; SingleDockableNode baseDockable = null; // used when there are tabs for (int i=0; i < dockables.getLength(); i++){ Element dockableElt = (Element) dockables.item(i); Element hideElt = (Element)dockableElt.getElementsByTagName("RelativePosition").item(0); float x = Float.parseFloat(hideElt.getAttribute("x")); float y = Float.parseFloat(hideElt.getAttribute("y")); float w = Float.parseFloat(hideElt.getAttribute("w")); float h = Float.parseFloat(hideElt.getAttribute("h")); RelativeDockablePosition position = new RelativeDockablePosition(x, y, w, h); SingleDockableNode dockable = xmlGetDockable(dockableElt); if (i == 0){ baseDockable = dockable; floating = new FloatingNode(baseDockable, rectangle, position); floatingNodes.add(floating); } Element previousState = (Element)dockableElt.getElementsByTagName("PreviousState").item(0); int istate = Integer.parseInt(previousState.getAttribute("state")); // @todo : see how to manage this value if (i > 0){ createTab(baseDockable.key, dockable.key, i); } if (dockable instanceof CompoundDockableNode){ // check for children and build them xmlBuildCompoundDockable((CompoundDockableNode) dockable, dockableElt, DockableState.STATE_FLOATING); } } } private void xmlBuildTabGroup(NodeList group) { for (int i=0; i < group.getLength(); i++){ Element groupElt = (Element)group.item(i); NodeList dockables = groupElt.getElementsByTagName("Dockable"); SingleDockableNode base = null; for (int j=0; j < dockables.getLength(); j++){ Element dockableElt = (Element)dockables.item(j); SingleDockableNode d = xmlGetDockable(dockableElt); if (j == 0){ base = d; } else { addToTabbedGroup(base.key, d.key); } } } } /** Registers a dockable as belonging to a tab group. *

It is used to have a memory of grouped (tabbed) dockables in order to keep the * group together when dockable are restored from auto-hide mode. *

This method is generally called by the tabbed container management, and not directly * by the developper. * *

However, there is a case where calling this method can be usefull : * when, at startup, a desktop is built with multiple hidden dockables, and the developper wants * them to be grouped in a tab container when they are restored to the desktop. * * @param base an already tabbed dockable * @param newTab a dockable to add to the tab group * *@since 1.1.2 */ public void addToTabbedGroup(WSDockKey base, WSDockKey newTab){ /* this method is called when a dockable is added to a dockableTabbedContainer */ LinkedList group = (LinkedList) tabbedGroups.get(base); if (group == null){ group = new LinkedList(); group.add(base); tabbedGroups.put(base, group); } group.add(newTab); tabbedGroups.put(newTab, group); } // ------- inner classes used to handle dockable layout /** abstract node into the layout */ private abstract class Node { Node parent; } /** a node describing a tab */ private class TabNode extends Node { ArrayList tabs = new ArrayList(); SingleDockableNode getTab(int index){ return (SingleDockableNode) tabs.get(index); } void addTab(int index, SingleDockableNode tab){ tabs.add(index, tab); tab.parent = this; } private void replaceTab(int index, SingleDockableNode node) { tabs.set(index, node); node.parent = this; } } /** a node containing a single dockable */ private class SingleDockableNode extends Node { WSDockKey key; SingleDockableNode(WSDockKey key){ this.key = key; nodesByKey.put(key, this); } } /** a single node that contains a whole dockable hierarchy */ private class CompoundDockableNode extends SingleDockableNode { Node nestedNode; CompoundDockableNode(WSDockKey key){ super(key); } void setNestedNode(Node nested){ nested.parent = this; nestedNode = nested; } } /** a node that represents a split */ private class SplitNode extends Node{ void setTop(Node node) { this.left = node; node.parent = this; } void setBottom(Node node) { this.right = node; node.parent = this; } void setLeft(Node node) { this.left = node; node.parent = this; } void setRight(Node node) { this.right = node; node.parent = this; } Node getTop(){ return left; } Node getBottom(){ return right; } Node getLeft(){ return left; } Node getRight(){ return right; } Node left, right; private double location; // proportional location (0-1) boolean isHorizontal; } /** a node describing a auto-hide dockable */ private class HiddenNode extends Node { private SingleDockableNode node; private RelativeDockablePosition position; HiddenNode(SingleDockableNode node, RelativeDockablePosition position){ this.node = node; node.parent = this; this.position = position; } void setChild(SingleDockableNode child){ child.parent = this; this.node = child; } } /** used as root node for main and hidden hierarchies */ private class TopLevelNode extends Node { Node child; void setChild(Node child){ this.child = child; child.parent = this; } } /** top container for floating dockables */ private class FloatingNode extends Node { private Node child; private Rectangle windowRect; private RelativeDockablePosition returnPosition; FloatingNode(Node child, Rectangle windowRect, RelativeDockablePosition returnPosition){ this.windowRect = windowRect; this.returnPosition = returnPosition; setChild(child); } void setChild(Node child){ this.child = child; child.parent = this; } } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/ws/WSDockKey.java0000644000175000017500000001344210573516350025341 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking.ws; import com.vlsolutions.swing.docking.DockingConstants; /** Defines a key associated to a dockable in a workspace. * * The internal "key" will have to match the one of a DockKey when the * worspace is applied to a DockingContext. * *

example : * if your application uses a dockable with DockKey k = new DockKey("testDockable");
* than your corresponding WSDockKey will be wsdk = new WSDockKey("testDockable"); *

* Design note : We use this class insted of DockKey because sometimes dockkeys are lazily * created (at dockable creation) and thus aren't already available when specifying a * workspace. * * @author Lilian Chamontin, VLSolutions */ public class WSDockKey { private String key; // must match DockKey#key private DockingConstants.Hide autoHideBorder; public WSDockKey(String key) { this.key = key; } public String toString(){ return key; } /** returns this object's hashcode */ public int hashCode(){ return key.hashCode(); } public boolean equals(Object o){ if (o instanceof WSDockKey){ return key.equals(((WSDockKey)o).key); } return false; } /** returns the inner key of this object (which must match a DockKey's 'key' instance variable) */ public String getKey() { return key; } /** Returns the autohide border of this dockable, or null if not set*/ public DockingConstants.Hide getAutoHideBorder(){ return autoHideBorder; } /** Updates the autohide border property */ public void setAutoHideBorder(DockingConstants.Hide border){ this.autoHideBorder = border; } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/ws/Workspace.java0000644000175000017500000002463710573516350025504 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking.ws; import com.vlsolutions.swing.docking.DockingContext; import com.vlsolutions.swing.docking.DockingDesktop; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.util.ArrayList; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; /** A logical organization of dockables. Used to define and save desktop layouts (xml loading in not supported yet). *

* A Workspace is composed of WSDesktop elements (one per involved desktop). *

* Each WSDesktop supports an API similar to the DockingDesktop (addDockable, split, createTab), where * arguments are simple DockKeys (and not Dockables). * *

Currently this version doesn't support dockable removal : you can create a workspace, but shouldn't alter its * layout by moving already positionned dockables elsewhere (e.g. workspace will fail if you install a dockable * on an auto-hide border, then add is as a docked tab later). * * * @author Lilian Chamontin, VLSolutions * @since 2.1.2 */ public class Workspace { private ArrayList desktops = new ArrayList(); /** Creates a workspace with a single default WSDesktop */ public Workspace() { desktops.add(new WSDesktop()); } /** Removes the contained desktops */ public void clear(){ desktops.clear(); } /** Adds a new desktop to this workspace */ public void addDesktop(WSDesktop desktop){ desktops.add(desktop); } /** Return the number of desktops contained in this workspace (default is 1 ) */ public int getDesktopCount(){ return desktops.size(); } /** Returns the index-th desktop contained */ public WSDesktop getDesktop(int index){ return (WSDesktop) desktops.get(index); } /** Returns a desktop identified by its name or null if not found */ public WSDesktop getDesktop(String desktopName){ if (desktops.size() == 1){ return (WSDesktop) desktops.get(0); } for (int i=0; i < desktops.size(); i++){ WSDesktop d = (WSDesktop) desktops.get(i); if (d.getDesktopName().equals(desktopName) ){ return d; } } return null; } /** Applies this workspace to the given docking context (this is equivalent as loading a * workspace file from DockingContext.readXML() : it removes every dockable from the context and * associated desktops, and clears their dockable states, then it reloads the dockables as specified * by this workspace layout. */ public void apply(DockingContext dockingContext) throws WorkspaceException { ByteArrayOutputStream outb = new ByteArrayOutputStream(); PrintWriter out = new PrintWriter(outb); out.println(""); out.println(""); for (int i=0; i < desktops.size(); i++){ WSDesktop desktop = (WSDesktop) desktops.get(i); desktop.writeDesktopNode(out); } out.println(""); out.close(); byte [] bytes = outb.toByteArray(); //System.out.println(new String(bytes)); ByteArrayInputStream is = new ByteArrayInputStream(bytes); try { dockingContext.readXML(is); } catch (Exception ex) { throw new WorkspaceException(ex); } finally { try { is.close(); } catch (Exception ignore) { } } } /** Loads and configures this workspace from a given docking context. *

* The workspace is then ready to be applied or saved as a stream. * @since 2.1.3 * @see #apply(DockingContext) */ public void loadFrom(DockingContext context) throws WorkspaceException{ try { ByteArrayOutputStream out = new ByteArrayOutputStream(); context.writeXML(out); out.close(); byte [] bytes = out.toByteArray(); //System.out.println(new String(bytes)); ByteArrayInputStream is = new ByteArrayInputStream(bytes); readXML(is); is.close(); } catch (Exception e){ throw new WorkspaceException(e); } } /** Saves the workspace layout into an XML stream. *

* The workspace is composed of every desktop layouts associated * with this workspace (desktops are identified by their 'desktopName' property). * *

* The stream is not closed at the end of the operation. * * @see #readXML(InputStream) * */ public void writeXML(OutputStream stream) throws IOException { PrintWriter out = new PrintWriter(stream); out.println(""); out.println(""); for (int i=0; i < desktops.size(); i++){ WSDesktop desktop = (WSDesktop) desktops.get(i); desktop.writeDesktopNode(out); } out.println(""); out.flush(); } public void readXML(InputStream in) throws ParserConfigurationException, IOException, SAXException { // remove all dockable states for (int i=0; i < desktops.size(); i++){ WSDesktop desk = (WSDesktop) desktops.get(i); desk.clear(); } DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document doc = builder.parse(in); Element root = doc.getDocumentElement(); if (root.getNodeName().equals("DockingDesktop")){ // this is an old desktop file, missing the VLDocking root node (VLDocking 2.0 format) // so we noly have a single desktop WSDesktop desk = getDesktop(0); // only one desk.readDesktopNode(root); } else { NodeList desktopChildren = root.getChildNodes(); for (int i = 0, len = desktopChildren.getLength(); i < len; i++) { Node node = desktopChildren.item(i); if (node instanceof Element){ Element deskChild = (Element) node; WSDesktop desk = getDesktop(deskChild.getAttribute("name")); desk.readDesktopNode(deskChild); } } } } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/ws/WorkspaceButton.java0000644000175000017500000000361210573516344026671 0ustar twernertwernerpackage com.vlsolutions.swing.docking.ws; import com.vlsolutions.swing.docking.DockingContext; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.Icon; import javax.swing.JButton; /** A simple button that applies a workspace to a given Docking context when pressed . * * @author Lilian Chamontin, VLSolutions * @since 2.1.3 * */ public class WorkspaceButton extends JButton { private Workspace workspace; private DockingContext ctx; private ActionListener actionListener = new ActionListener() { public void actionPerformed(ActionEvent e) { try { applyWorkspace(); } catch (WorkspaceException ex) { ex.printStackTrace(); } } }; /** default constructor */ public WorkspaceButton() { addActionListener(actionListener); } /** constructor with a menu text */ public WorkspaceButton(String text){ super(text); addActionListener(actionListener); } /** constructor with a menu text and an icon */ public WorkspaceButton(String text, Icon icon){ super(text, icon); addActionListener(actionListener); } /** Invoked when the button is pressed : applies the workspace to the associated context */ public void applyWorkspace() throws WorkspaceException { workspace.apply(ctx); } /** Returns the workspace used by this button */ public Workspace getWorkspace() { return workspace; } /** updates the workspace to be used by this button */ public void setWorkspace(Workspace workspace) { this.workspace = workspace; } /** Returns the docking context used by this button */ public DockingContext getDockingContext() { return ctx; } /** Updates the docking context used by this button */ public void setDockingContext(DockingContext ctx) { this.ctx = ctx; } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/ws/WorkspaceException.java0000644000175000017500000001114310573516350027347 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking.ws; /** An exception raised when a workspace operation has gone wrong (can encapsulate * another exception). * * @author Lilian Chamontin, VLSolutions */ public class WorkspaceException extends Exception{ public WorkspaceException(String message) { super(message); } public WorkspaceException(Exception cause) { super(cause); } public WorkspaceException(String message, Exception cause) { super(message, cause); } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/ws/WorkspaceMenuItem.java0000644000175000017500000000365710573516344027152 0ustar twernertwernerpackage com.vlsolutions.swing.docking.ws; import com.vlsolutions.swing.docking.DockingContext; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.Icon; import javax.swing.JMenuItem; /** A simple menu item that applies a workspace to a given Docking context when selected . * * @author Lilian Chamontin, VLSolutions * @since 2.1.3 */ public class WorkspaceMenuItem extends JMenuItem { private Workspace workspace; private DockingContext ctx; private ActionListener actionListener = new ActionListener() { public void actionPerformed(ActionEvent e) { try { applyWorkspace(); } catch (WorkspaceException ex) { ex.printStackTrace(); } } }; /** Default constructor */ public WorkspaceMenuItem() { addActionListener(actionListener); } /** constructor with a menu text */ public WorkspaceMenuItem(String text){ super(text); addActionListener(actionListener); } /** constructor with a menu text and an icon */ public WorkspaceMenuItem(String text, Icon icon ){ super(text, icon ); addActionListener(actionListener); } /** Invoked when the button is pressed : applies the workspace to the associated context */ public void applyWorkspace() throws WorkspaceException { workspace.apply(ctx); } /** Returns the workspace used by this menu item */ public Workspace getWorkspace() { return workspace; } /** updates the workspace to be used by this menu item */ public void setWorkspace(Workspace workspace) { this.workspace = workspace; } /** Returns the docking context used by this menu item */ public DockingContext getDockingContext() { return ctx; } /** Updates the docking context used by this menu item */ public void setDockingContext(DockingContext ctx) { this.ctx = ctx; } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/AnchorConstraints.java0000644000175000017500000001262710573516346026560 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking; /** A constraint used to specify how a dockable is tied (anchored) to its containing parent . * * @author Lilian Chamontin, VLSolutions * @since 2.1 */ public class AnchorConstraints { /** Field describing a dockable anchored to the TOP border of its ancestor container */ public static final int ANCHOR_TOP = 1; /** Field describing a dockable anchored to the LEFT border of its ancestor container */ public static final int ANCHOR_LEFT = 2; /** Field describing a dockable anchored to the BOTTOM border of its ancestor container */ public static final int ANCHOR_BOTTOM = 4; /** Field describing a dockable anchored to the RIGHT border of its ancestor container */ public static final int ANCHOR_RIGHT = 8; private int anchor; /** Constructor for an immutable contraints * *@param anchor value expressed as a bitwise OR between ANCHOR_ fields (for example ANCHOR_TOP|ANCHOR_LEFT) * */ public AnchorConstraints(int anchor) { this.anchor = anchor; } /** Returns the anchor value of this contraints object. *

* Anchor is expressed as a bitwise OR between ANCHOR_ fields (for example ANCHOR_TOP|ANCHOR_LEFT) */ public int getAnchor() { return anchor; } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/AnchorManager.java0000644000175000017500000004303210573516346025615 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking; import com.vlsolutions.swing.docking.event.DockingActionAddDockableEvent; import com.vlsolutions.swing.docking.event.DockingActionCreateTabEvent; import com.vlsolutions.swing.docking.event.DockingActionEvent; import com.vlsolutions.swing.docking.event.DockingActionListener; import com.vlsolutions.swing.docking.event.DockingActionSplitComponentEvent; import com.vlsolutions.swing.docking.event.DockingActionSplitDockableContainerEvent; import com.vlsolutions.swing.docking.event.DockingActionSplitDockableEvent; import java.awt.Component; import java.awt.Container; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import javax.swing.JSplitPane; /** A helper class used to specify and enforce constraints within a container * (DockingPanel or CompoundDockingPanel). *

* Constraints are currently defined as anchors (AnchorConstraints objects associated to Dockables). * * @author Lilian Chamontin, VLSolutions * @see AnchorConstraints * @since 2.1 */ public class AnchorManager { /** Top most ancestor container */ private Container container; /** Map of AnchorConstraints (value) associated to Dockables (key) */ private HashMap constraintsByDockable = new HashMap(); /** Context where docking action events are listened to */ private DockingContext context; /** Appropriate reaction upon docking actions (vetoing the ones that would break constraints) */ private DockingActionListener actionListener = new DockingActionListener() { public boolean acceptDockingAction(DockingActionEvent event) { switch (event.getActionType()){ case DockingActionEvent.ACTION_ADD_DOCKABLE:{ DockingActionAddDockableEvent e = (DockingActionAddDockableEvent) event; return acceptAddDockable(e); } case DockingActionEvent.ACTION_CREATE_TAB:{ DockingActionCreateTabEvent e = (DockingActionCreateTabEvent) event; return acceptCreateTab(e); } case DockingActionEvent.ACTION_SPLIT_COMPONENT:{ DockingActionSplitComponentEvent e = (DockingActionSplitComponentEvent) event; return acceptSplitComponent(e); } case DockingActionEvent.ACTION_SPLIT_DOCKABLE: { DockingActionSplitDockableEvent e = (DockingActionSplitDockableEvent) event; return acceptSplitDockable(e); } case DockingActionEvent.ACTION_SPLIT_DOCKABLE_CONTAINER:{ DockingActionSplitDockableContainerEvent e = (DockingActionSplitDockableContainerEvent) event; return acceptSplitDockableContainer(e); } default : return true; // accepting everything else } } public void dockingActionPerformed(DockingActionEvent event) { } }; /** Constructs a new AnchorManager responsible for a container (desktop or compound) * * @param context the context (can be taken from DockingDesktop.getDockingContext() used by this manager * @param container the "top level" container managed (usually a DockingDesktop or a CompoundDockingPanel) */ public AnchorManager(DockingContext context, Container container) { this.context = context; this.container = container; context.addDockingActionListener(actionListener); } /** Cleanup for this manager : removes references and listeners */ public void clear(){ context.removeDockingActionListener(actionListener); constraintsByDockable.clear(); } /** Associates an anchor constraints to a given dockable * @param dockable the dockable to anchor * @param constraints associated anchor constraints */ public void putDockableContraints(Dockable dockable, AnchorConstraints constraints){ constraintsByDockable.put(dockable, constraints); } /** Returns the anchor constraints associated to a given dockable * @param dockable the dockable to anchor * @return the constraints for this dockable, or null if no constraints is associated */ public AnchorConstraints getDockableConstraints(Dockable dockable){ return (AnchorConstraints) constraintsByDockable.get(dockable); } /** Removes an anchor constraints to a given dockable * @param dockable the dockable whose anchor is to be removed */ public AnchorConstraints removeDockableConstraints(Dockable dockable){ return (AnchorConstraints) constraintsByDockable.remove(dockable); } /** Look up the spilt hierarchy to find which borders a dockable is touching. * */ private int getContactBorders(Dockable dockable){ return RelativeDockingUtilities.findAnchors(dockable.getComponent(), container); } /** Returns a list of all dockables contained into base */ private ArrayList findDockables(Container base){ ArrayList dockables = new ArrayList(10); Iterator it = constraintsByDockable.keySet().iterator(); while (it.hasNext()){ Dockable d = (Dockable) it.next(); if (base.isAncestorOf(d.getComponent())){ dockables.add(d); } } return dockables; } private boolean acceptSplitComponent(DockingActionSplitComponentEvent event ){ Component base = event.getBase(); ArrayList baseDockables = findDockables((Container)base); // we suppose that dockables in "base" are ok (respecting their own set of constraints before the split) // we still have to check is splitting will break a constraint or not int contactBorders = RelativeDockingUtilities.findAnchors(base, container); switch (event.getSplitPosition().value()){ case DockingConstants.INT_SPLIT_TOP: // as we won't be touching TOP anymore, check if this // constraint is not set in contained dockables if (isConstraintSet(AnchorConstraints.ANCHOR_TOP, baseDockables)){ return false; } contactBorders = contactBorders & ~AnchorConstraints.ANCHOR_BOTTOM; break; case DockingConstants.INT_SPLIT_LEFT: if (isConstraintSet(AnchorConstraints.ANCHOR_LEFT, baseDockables)){ return false; } contactBorders = contactBorders & ~AnchorConstraints.ANCHOR_RIGHT; break; case DockingConstants.INT_SPLIT_BOTTOM: if (isConstraintSet(AnchorConstraints.ANCHOR_BOTTOM, baseDockables)){ return false; } contactBorders = contactBorders & ~AnchorConstraints.ANCHOR_TOP; break; case DockingConstants.INT_SPLIT_RIGHT: if (isConstraintSet(AnchorConstraints.ANCHOR_RIGHT, baseDockables)){ return false; } contactBorders = contactBorders & ~AnchorConstraints.ANCHOR_LEFT; break; } // now, we're sure we won't break a 'base' constraint // we have to check if the moved dockable will respect its own constraints AnchorConstraints acDockable = getDockableConstraints(event.getDockable()); if (acDockable != null){ int anchor = acDockable.getAnchor(); if ((anchor & contactBorders) != anchor){ // anchor is not respected return false; } } return true; } private boolean acceptSplitDockable(DockingActionSplitDockableEvent event ){ // two rules to enforce : // the added component must respect its own set of constraints // the base dockable, once the new component added, must also respect its own set of constraints Dockable base = event.getBase(); AnchorConstraints acBase = getDockableConstraints(base); int contactBorders = getContactBorders(base); switch (event.getSplitPosition().value()){ case DockingConstants.INT_SPLIT_TOP: // as we won't be touching TOP anymore, check if this // constraint is not set in contained dockables if (isConstraintSet(AnchorConstraints.ANCHOR_TOP, base)){ return false; } contactBorders = contactBorders & ~AnchorConstraints.ANCHOR_BOTTOM; break; case DockingConstants.INT_SPLIT_LEFT: if (isConstraintSet(AnchorConstraints.ANCHOR_LEFT, base)){ return false; } contactBorders = contactBorders & ~AnchorConstraints.ANCHOR_RIGHT; break; case DockingConstants.INT_SPLIT_BOTTOM: if (isConstraintSet(AnchorConstraints.ANCHOR_BOTTOM, base)){ return false; } contactBorders = contactBorders & ~AnchorConstraints.ANCHOR_TOP; break; case DockingConstants.INT_SPLIT_RIGHT: if (isConstraintSet(AnchorConstraints.ANCHOR_RIGHT, base)){ return false; } contactBorders = contactBorders & ~AnchorConstraints.ANCHOR_LEFT; break; } // now, we're sure we won't break a 'base' constraint // we have to check if the moved dockable will respect its own constraints AnchorConstraints acDockable = getDockableConstraints(event.getDockable()); if (acDockable != null){ int anchor = acDockable.getAnchor(); if ((anchor & contactBorders) != anchor){ // anchor is not respected return false; } } return true; } private boolean acceptSplitDockableContainer(DockingActionSplitDockableContainerEvent event ){ Component base = event.getBase(); ArrayList baseDockables = findDockables((Container)base); // we suppose that dockables in "base" are ok (respecting their own set of constraints before the split) // we still have to check is splitting will break a constraint or not int contactBorders = RelativeDockingUtilities.findAnchors(base, container); switch (event.getSplitPosition().value()){ case DockingConstants.INT_SPLIT_TOP: // as we won't be touching TOP anymore, check if this // constraint is not set in contained dockables if (isConstraintSet(AnchorConstraints.ANCHOR_TOP, baseDockables)){ return false; } contactBorders = contactBorders & ~AnchorConstraints.ANCHOR_BOTTOM; break; case DockingConstants.INT_SPLIT_LEFT: if (isConstraintSet(AnchorConstraints.ANCHOR_LEFT, baseDockables)){ return false; } contactBorders = contactBorders & ~AnchorConstraints.ANCHOR_RIGHT; break; case DockingConstants.INT_SPLIT_BOTTOM: if (isConstraintSet(AnchorConstraints.ANCHOR_BOTTOM, baseDockables)){ return false; } contactBorders = contactBorders & ~AnchorConstraints.ANCHOR_TOP; break; case DockingConstants.INT_SPLIT_RIGHT: if (isConstraintSet(AnchorConstraints.ANCHOR_RIGHT, baseDockables)){ return false; } contactBorders = contactBorders & ~AnchorConstraints.ANCHOR_LEFT; break; } // now, we're sure we won't break a 'base' constraint // we have to check if the moved dockable container will respect its own constraints if (event.getDockableContainer() instanceof TabbedDockableContainer){ // the only one managed currently (drag gesture : move a whole tabbed pane around) ArrayList containersDockables = findDockables(event.getDockableContainer()); // check if these dockable have constraints for (int i=0; i < containersDockables.size(); i++){ Dockable d = (Dockable) containersDockables.get(i); AnchorConstraints acDockable = getDockableConstraints(d); if (acDockable != null){ int anchor = acDockable.getAnchor(); if ((anchor & contactBorders) != anchor){ // anchor is not respected return false; } } } } return true; } private boolean acceptAddDockable(DockingActionAddDockableEvent event ){ Container parent = event.getParentContainer(); int contactBorders = RelativeDockingUtilities.findAnchors(parent, container); Dockable d = event.getDockable(); AnchorConstraints acDockable = getDockableConstraints(d); if (acDockable != null){ int anchor = acDockable.getAnchor(); if ((anchor & contactBorders) != anchor){ // anchor is not respected return false; } } return true; } private boolean acceptCreateTab(DockingActionCreateTabEvent event ){ int contactBorders = getContactBorders(event.getBase()); Dockable d = event.getDockable(); AnchorConstraints acDockable = getDockableConstraints(d); if (acDockable != null){ int anchor = acDockable.getAnchor(); if ((anchor & contactBorders) != anchor){ // anchor is not respected return false; } } return true; } /** checks if a given anchor is set into one of the given dockables*/ private boolean isConstraintSet(int anchor, ArrayList baseDockables) { for (int i=0; i < baseDockables.size(); i++){ AnchorConstraints ac = (AnchorConstraints) constraintsByDockable.get(baseDockables.get(i)); if (ac != null){ // 2007/01/08 if ((ac.getAnchor() & anchor) > 0){ return true; } } } return false; } /** checks if a given anchor is set for a dockable*/ private boolean isConstraintSet(int anchor, Dockable dockable) { AnchorConstraints ac = (AnchorConstraints) constraintsByDockable.get(dockable); if (ac == null){ //2007/01/08 return false; } if ((ac.getAnchor() & anchor) > 0){ return true; } return false; } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/AutoHideBorderLayout.java0000644000175000017500000001764210573516346027156 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking; import java.util.*; import java.awt.*; /** A Layout Manager for auto-hide borders. * * @author Lilian Chamontin, vlsolutions. * @version 1.0 */ public class AutoHideBorderLayout implements LayoutManager2{ private ArrayList components = new ArrayList(); private boolean isHorizontal; private int gap; // gap in pixels between components /** Constructs a new Layout. * * @param isHorizontal indicates if the layout will be horizontal or vertical. * * */ public AutoHideBorderLayout(boolean isHorizontal) { this(isHorizontal, AutoHidePolicy.getPolicy().getDefaultGap()); /** @todo we do not yet listen to gap property change */ } /** Constructs a new Layout. * @param isHorizontal indicates if the layout will be horizontal or vertical. * @param gap gap in pixels between components * */ public AutoHideBorderLayout(boolean isHorizontal, int gap) { this.isHorizontal = isHorizontal; this.gap = gap; } public float getLayoutAlignmentX(Container target) { return 0.5F; } public float getLayoutAlignmentY(Container target) { return 0.5F; } public void invalidateLayout(Container target) { } public Dimension maximumLayoutSize(Container target) { return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); } public void addLayoutComponent(Component comp, Object constraints) { if (constraints == null){ components.add(comp); } else { Integer i = (Integer) constraints; components.add(i.intValue(), comp); } } public void removeLayoutComponent(Component comp) { components.remove(comp); } public void addLayoutComponent(String name, Component comp) { } public Dimension minimumLayoutSize(Container parent) { synchronized (parent.getTreeLock()) { Dimension dim = new Dimension(0, 0); int visible = 0; for (int i = 0; i < components.size(); i++) { Component comp = (Component) components.get(i); Dimension d = comp.getPreferredSize(); if (comp.isVisible()){ visible ++; if (isHorizontal) { dim.width += d.width; dim.height = Math.max(dim.height, d.height); } else { dim.width = Math.max(dim.width, d.width); dim.height += d.height; } } } // add the gap between components if (isHorizontal) { dim.width += (visible - 1) * gap; } else { dim.height += (visible - 1) * gap; } Insets insets = parent.getInsets(); dim.width += insets.left + insets.right; dim.height += insets.top + insets.bottom; return dim; } } public Dimension preferredLayoutSize(Container parent) { return minimumLayoutSize(parent); } /** overridden to adjust position (x(top) = width(left), y(left) = height(top) */ public void layoutContainer(Container target) { synchronized (target.getTreeLock()) { Insets insets = target.getInsets(); int top = insets.top; int left = insets.left; if (isHorizontal){ for (int i = 0; i < components.size(); i++) { Component comp = (Component) components.get(i); if (comp.isVisible()){ Dimension d = comp.getPreferredSize(); comp.setBounds(left, top, d.width, d.height); left += d.width + gap; } } } else { for (int i = 0; i < components.size(); i++) { Component comp = (Component) components.get(i); if (comp.isVisible()){ Dimension d = comp.getPreferredSize(); comp.setBounds(left, top, d.width, d.height); top += d.height + gap; } } } } } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/AutoHideButton.java0000644000175000017500000002403010573516346026003 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking; import javax.swing.*; import javax.swing.border.Border; import java.awt.event.ActionEvent; import java.awt.Font; import java.awt.event.MouseListener; import java.awt.event.ActionListener; import java.awt.Component; import java.awt.Insets; import java.awt.Graphics2D; import java.awt.Dimension; import java.awt.Graphics; import java.awt.FontMetrics; import java.awt.Color; import java.beans.*; /** The button used to show Dockables in auto-hide borders. *

* This component displays the label, tooltip and icon properties of a * Dockable's DockKey, with a custom look and feel. * * * @author Lilian Chamontin, vlsolutions. * @version 1.0 */ public class AutoHideButton extends JLabel { /** property name associated to the "zone" (border) property */ public static final String PROPERTY_ZONE = "autohide.zone"; public static final String uiClassID = "AutoHideButtonUI"; private boolean selected = false; private DockKey key; private Dockable dockable; private int zone; // the border used private boolean isNotification = false; private Timer notificationTimer; // blinking timer private int blinkCount = 0; private int MAX_BLINKS = UIManager.getInt("DockingDesktop.notificationBlinkCount"); private PropertyChangeListener keyListener = new PropertyChangeListener(){ // this is a DockKey listener, not a KeyEvent listener... public void propertyChange(PropertyChangeEvent e) { if (e.getPropertyName().equals(DockKey.PROPERTY_NAME)){ setText((String)e.getNewValue()); } else if (e.getPropertyName().equals(DockKey.PROPERTY_TOOLTIP)){ setToolTipText((String)e.getNewValue()); } else if (e.getPropertyName().equals(DockKey.PROPERTY_ICON)){ setIcon((Icon) e.getNewValue()); } else if (e.getPropertyName().equals(DockKey.PROPERTY_NOTIFICATION)){ boolean isOn = ((Boolean)e.getNewValue()).booleanValue(); if (isOn){ if (notificationTimer == null){ notificationTimer = new Timer(1000, new ActionListener() { public void actionPerformed(ActionEvent actionEvent) { setNotification(!isNotification); if (!isNotification){ blinkCount ++; if (blinkCount >= MAX_BLINKS){ blinkCount = 0; notificationTimer.stop(); // enough blinking } } repaint(); } }); } setNotification(true); notificationTimer.restart(); } else { if (notificationTimer != null){ notificationTimer.stop(); blinkCount = 0; } setNotification(false); } } } }; public AutoHideButton() { } /** Sets the background color according to the notification boolean */ private void setNotification(boolean notification){ this.isNotification = notification; if (notification){ setBackground(UIManager.getColor("DockingDesktop.notificationColor")); setOpaque(true); } else { setOpaque(false); } repaint(); } /** Returns the dockable this button is for */ public Dockable getDockable(){ return dockable; } /** Returns the key of the dockable */ public DockKey getKey(){ return key; } /** Initialize the button for a Dockable and a border zone */ public void init(Dockable dockable, int zone){ DockKey key = dockable.getDockKey(); this.dockable = dockable; this.key = key; int oldZone = this.zone; this.zone = zone; firePropertyChange("autohide.zone", oldZone, zone); key.addPropertyChangeListener(keyListener); setText(key.getName()); setToolTipText(key.getTooltip()); if (key.getIcon() != null) { setIcon(key.getIcon()); } setFocusable(true); setOpaque(false); setIconTextGap(4); setAlignmentY(1); } public Dimension getPreferredSize() { if (zone == DockingConstants.INT_HIDE_TOP || zone == DockingConstants.INT_HIDE_BOTTOM) { return super.getPreferredSize(); } else { Dimension d = super.getPreferredSize(); Insets i = getInsets(); return new Dimension(d.height - i.top - i.bottom + i.left + i.right, d.width - i.left - i.right + i.top + i.bottom); // rotate the shape } } public Dimension getMaximumSize() { if (zone == DockingConstants.INT_HIDE_TOP || zone == DockingConstants.INT_HIDE_BOTTOM) { return super.getMaximumSize(); } else { Insets i = getInsets(); Dimension d = super.getMaximumSize(); return new Dimension(d.height - i.top - i.bottom + i.left + i.right, d.width - i.left - i.right + i.top + i.bottom); // rotate the shape } } public Dimension getMinimumSize() { if (zone == DockingConstants.INT_HIDE_TOP || zone == DockingConstants.INT_HIDE_BOTTOM) { return super.getMinimumSize(); } else { Insets i = getInsets(); Dimension d = super.getMinimumSize(); return new Dimension(d.height - i.top - i.bottom + i.left + i.right, d.width - i.left - i.right + i.top + i.bottom); // rotate the shape } } /** Returns the border zone of this button*/ public int getZone(){ return zone; } /** True when the button is currently selected. */ public boolean isSelected(){ return selected; } /** Selects or unselects the button */ public void setSelected(boolean selected){ this.selected = selected; setOpaque(selected); repaint(); if (selected){ key.setNotification(false); // in case we were in notification mode } } public String getUIClassID() { return uiClassID; } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/AutoHideButtonPanel.java0000644000175000017500000001627410573516346026776 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking; import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.beans.*; /** A Swing panel used as a toolbar for autohide buttons. * * @author Lilian Chamontin, vlsolutions. * @version 1.0 * */ public class AutoHideButtonPanel extends JPanel { /** The property name associated with the "border" property */ public static final String PROPERTY_BORDERZONE = "borderzone"; public static final String uiClassID = "AutoHideButtonPanelUI"; /** <=> Zone */ private int border; /** highlight effect (rollover) on the contained buttons */ private ButtonHighlighter buttonHighlighter = new ButtonHighlighter(); /** expansion management */ private AutoHideExpandPanel expandPanel; /** Constructs a new AutoHideButtonPanel, with a shared expandPanel, and for * a specified border zone. * * @param border constant taken from AutoHideButtonPanel.TOP, AutoHideButtonPanel.LEFT, * AutoHideButtonPanel.BOTTOM, AutoHideButtonPanel.RIGHT * */ public AutoHideButtonPanel(AutoHideExpandPanel expandPanel, int border) { this.border = border; this.expandPanel = expandPanel; boolean isHorizontal = (border == DockingConstants.INT_HIDE_TOP) || (border == DockingConstants.INT_HIDE_BOTTOM); setLayout(new AutoHideBorderLayout(isHorizontal)); firePropertyChange("borderzone", -1, border); } /** Returns the number of buttons currently displayed by this panel. */ public int getVisibleButtonCount(){ Component [] comps = getComponents(); int count = 0; for (int i=0; i < comps.length; i++){ if (comps[i].isVisible()){ count ++; } } return count; } /** Returns the border this panel is for. *

* Values are : AutoHideButtonPanel.TOP, AutoHideButtonPanel.LEFT, * AutoHideButtonPanel.BOTTOM, AutoHideButtonPanel.RIGHT */ public int getBorderZone(){ return border; } /** Adds a new AutoHideButton. * */ public void add(AutoHideButton btn){ add((Component)btn); btn.addMouseListener(buttonHighlighter); btn.addMouseListener(expandPanel.getControler()); } /** Removes an AutoHideButton */ public void remove(AutoHideButton btn){ super.remove(btn); btn.removeMouseListener(buttonHighlighter); } private class ButtonHighlighter extends MouseAdapter { Color highlight = UIManager.getColor("controlLtHighlight"); public void mouseEntered(MouseEvent e){ AutoHideButton btn = (AutoHideButton) e.getSource(); if (! btn.isSelected()){ // selected buttons have their own pain style btn.setBackground(highlight); btn.setOpaque(true); btn.repaint(); } } public void mouseExited(MouseEvent e){ AutoHideButton btn = (AutoHideButton) e.getSource(); if (! btn.isSelected()){ // selected buttons have their own pain style btn.setOpaque(false); btn.repaint(); } } } public String getUIClassID() { return uiClassID; } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/AutoHideExpandPanel.java0000644000175000017500000011736210573516346026742 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking; import java.beans.*; import java.awt.event.*; import java.lang.reflect.InvocationTargetException; import javax.swing.*; import java.awt.*; import java.util.HashMap; import com.vlsolutions.swing.docking.animation.ComponentAnimator; import com.vlsolutions.swing.docking.animation.*; import java.lang.reflect.Method; import javax.swing.border.*; import javax.swing.event.AncestorEvent; import javax.swing.event.AncestorListener; /** A component used to show the currently expanded view. *

* Auto-Hide / Auto-Expand feature is a means to save space of screen replacing * a Dockable by a Button on one of the Desktop borders. *

When the user clicks on the button or his mouse rolls over it, the component * is shown (with an expansion animation) as if it was coming from behind the button's * border. * * @author Lilian Chamontin, vlsolutions. * @version 2.0 * @update 2005/10/06 Lilian Chamontin : protected access to the exansion timer that might be * null when AutoHidePolicy is EXPAND_ON_CLICK * @update 2005/11/01 Lilian Chamontin : enhanced timer management to auto-collaspe the panel * when mouse out of bounds * @update 2005/12/08 Lilian Chamontin : updated the order of component insertion for JDIC support. * @update 2006/12/19 Lilian Chamontin : fixed a memory leak issue. * @update 2007/01/08 Lilian Chamontin : updated to use the new titlebar factory method * * */ public class AutoHideExpandPanel extends JPanel implements SingleDockableContainer { public static final String uiClassID = "AutoHideExpandPanelUI"; /** Constant for the Expanded property (a bound property) */ public static final String PROPERTY_EXPANDED = "AutoHideExpanded"; private Timer expansionTimer; private boolean isRolloverTimer = false; private boolean isExpanding = false; // true during animation phase, will be used to avoid concurrent animations (@todo) private HashMap savedDimensions = new HashMap(); // Component/Dimension ExpandControler controler = new ExpandControler(); // hide event listener private AutoHideButton selectedButton; private Component expandedComponent; // current component DockingDesktop desk; private JPanel topDragger = getTopDragger(); // indirection because those components are used by the ui delegate private JPanel leftDragger = getLeftDragger(); private JPanel bottomDragger = getBottomDragger(); private JPanel rightDragger = getRightDragger(); private JPanel lastDragger; // last used dragger private JPanel content = new JPanel(new BorderLayout()); // content displayed (user component) private Panel heavyPanel; // used only when mixing lightweight and heavyweight components private DockViewTitleBar titleBar = createTitleBar(); private AnimationControler animationControler = new AnimationControler(); private Border expandFromTopBorder, expandFromLeftBorder, expandFromBottomBorder, expandFromRightBorder; /** this boolean is used to disable auto-hiding temporarily, especially during * drag operation (where mouse can leave the component) */ private boolean shouldCollapse = true; /** flag used when heavywieght usage + single heavyweight component */ private boolean isHeavyPanelInstalled = false; /** Used by the collapse timer*/ private long lastTimeMouseWasIn = 0; private boolean canUseMouseInfo = DockingUtilities.canUseMouseInfo(); private FocusCollapser collapser = new FocusCollapser(); // 2006/12/19 /** Timer used to collapse the expand panel (when mouse is out of bounds). * (only for java > 1.5) */ private javax.swing.Timer collapseTimer // 2005/11/01 = new javax.swing.Timer(250, new ActionListener() { // timer used to hide the expanded panel when mouse is out too long public void actionPerformed(ActionEvent actionEvent) { // all this mess to allow compilation from java 1.4 Point mouseLocation = DockingUtilities.getMouseLocation(); if (mouseLocation == null){ return; } Point p = new Point(); SwingUtilities.convertPointToScreen(p, AutoHideExpandPanel.this); Rectangle expandPanelBounds = new Rectangle(p.x, p.y, getWidth(), getHeight()); if (expandPanelBounds.contains(mouseLocation)){ // we're inside the expand panel lastTimeMouseWasIn = System.currentTimeMillis(); } else { // not inside the component : check also into its associated button Point btnPoint = new Point();//selectedButton.getX(),selectedButton.getY()); SwingUtilities.convertPointToScreen(btnPoint, selectedButton); Rectangle btnRect = new Rectangle(btnPoint.x, btnPoint.y, selectedButton.getWidth(), selectedButton.getHeight()); if (btnRect.contains(mouseLocation)){ lastTimeMouseWasIn = System.currentTimeMillis(); } else { if (System.currentTimeMillis() - lastTimeMouseWasIn > 1000 ){ // it's time to collapse if (!isActive() && shouldCollapse()) { // do not hide it if it has got the focus // or if a non-collapsible operation is occuring if (selectedButton != null){ collapse(); } } } } } } }); public AutoHideExpandPanel() { super(new BorderLayout()); if (!DockingPreferences.isLightWeightUsageEnabled()){ this.heavyPanel = new Panel(new BorderLayout()); } if (AutoHidePolicy.getPolicy().getExpandMode() == AutoHidePolicy.EXPAND_ON_ROLLOVER) { expansionTimer = new Timer(AutoHidePolicy.getPolicy(). getRolloverTriggerDelay(), controler); expansionTimer.setRepeats(false); isRolloverTimer = true; } initBorders(); setFocusCycleRoot(true); // keep keyboard focus //requiered to trap mouse events under the panel (so they don't go to the mousegrabber) addMouseListener(new MouseAdapter(){ }); if (DockingPreferences.isLightWeightUsageEnabled()){ // for Swing only : direct usage of the content jpanel add(content, BorderLayout.CENTER); } else { if (!DockingPreferences.isSingleHeavyWeightComponent()){ // when mixing heavyweight and lightweight component, we have // to ensure our content will not be covered by an underlying heavy component. // to do this, we add an intermediary heavyweight panel. // note : if there is only one heavyweight dockable, // we delay and delegate this operation to installHeavyWeightIfNeeded heavyPanel.add(content, BorderLayout.CENTER); // jdk1.5 only, but we compile with 1.4 source level try { // this.setComponentZOrder(heavyPanel, 0); // top most Method m = Container.class.getMethod("setComponentZOrder", new Class[]{ Component.class, int.class}); m.invoke(this, new Object[]{heavyPanel, new Integer(0)}); } catch (Exception ignore){ } add(heavyPanel, BorderLayout.CENTER); } else { // (heavy + single) will be dynamically changed depending on the expanded dockable add(content, BorderLayout.CENTER); add(topDragger, BorderLayout.NORTH); add(bottomDragger, BorderLayout.SOUTH); add(leftDragger, BorderLayout.WEST); add(rightDragger, BorderLayout.EAST); } } addAncestorListener(new AncestorListener() { //2006/12/19 : reworked to avoid GC leak public void ancestorAdded(AncestorEvent event) { AutoHidePolicy.getPolicy().addPropertyChangeListener(controler); if (DockingPreferences.isLightWeightUsageEnabled()){ KeyboardFocusManager.getCurrentKeyboardFocusManager().addPropertyChangeListener( "focusOwner", collapser); } } public void ancestorMoved(AncestorEvent event) { } public void ancestorRemoved(AncestorEvent event) { AutoHidePolicy.getPolicy().removePropertyChangeListener(controler); if (DockingPreferences.isLightWeightUsageEnabled()){ KeyboardFocusManager.getCurrentKeyboardFocusManager().removePropertyChangeListener( "focusOwner", collapser); } } }); content.add(titleBar, BorderLayout.NORTH); // initDockingFunctions(); } private void installHeavyWeightParentIfNeeded(Dockable target){ if (DockingPreferences.isLightWeightUsageEnabled()){ return; // not needed as we are in pure lightweight } if (!DockingPreferences.isSingleHeavyWeightComponent()){ return; // not possible as there are multiple heavyweight } if (DockingUtilities.isHeavyWeightComponent(target.getComponent())){ // no need to install the heavypanel if (isHeavyPanelInstalled){ // we even have to remove it this.removeAll(); this.add(content, BorderLayout.CENTER); add(topDragger, BorderLayout.NORTH); add(bottomDragger, BorderLayout.SOUTH); add(leftDragger, BorderLayout.WEST); add(rightDragger, BorderLayout.EAST); revalidate(); isHeavyPanelInstalled = false; } } else { if (isHeavyPanelInstalled){ // nothing more to do, content is already inside heavypanel } else { this.removeAll(); this.add(heavyPanel, BorderLayout.CENTER); heavyPanel.add(content, BorderLayout.CENTER); heavyPanel.add(topDragger, BorderLayout.NORTH); heavyPanel.add(bottomDragger, BorderLayout.SOUTH); heavyPanel.add(leftDragger, BorderLayout.WEST); heavyPanel.add(rightDragger, BorderLayout.EAST); isHeavyPanelInstalled = true; revalidate(); // jdk1.5 only, but we compile with 1.4 source level try { // this.setComponentZOrder(heavyPanel, 0); // top most Method m = Container.class.getMethod("setComponentZOrder", new Class[]{ Component.class, int.class}); m.invoke(this, new Object[]{heavyPanel, new Integer(0)}); } catch (Exception ignore){ } } } } public boolean isOptimizedDrawingEnabled(){ return DockingPreferences.isLightWeightUsageEnabled(); // only when lightweight components (to ensure correct zorder for AWT) } /** Returns true if this panel is the ancestor of the focused component */ public boolean isActive() { if (titleBar.isActive()){ return true; } else { // since 2.1 : the autohide component can contain a nested set of dockables, so the // titlebar's activity isn't always usable : we have to verify if the focus is still // inside Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); if (focusOwner == null){ return false; } else { return isAncestorOf(focusOwner); } } //return titleBar.isActive(); } /** Returns true if this panel agrees to beeing hidden. *

* During drag operations (resizing), some mouseEnter/mouseExit events * can be lost. In that case, the desktop relies on this method to * request collaping or not. * */ public boolean shouldCollapse(){ return shouldCollapse; } /** Returns the component used to modify the expand panel size when expanded from the bottom */ public JPanel getTopDragger(){ /* This method is used by the UI to install proper borders */ if (topDragger == null){ topDragger = new JPanel(); } return topDragger; } /** Returns the component used to modify the expand panel size when expanded from the right */ public JPanel getLeftDragger(){ /* This method is used by the UI to install proper borders */ if (leftDragger == null){ leftDragger = new JPanel(); } return leftDragger; } /** Returns the component used to modify the expand panel size when expanded from the top */ public JPanel getBottomDragger(){ /* This method is used by the UI to install proper borders */ if (bottomDragger == null){ bottomDragger = new JPanel(); } return bottomDragger; } /** Returns the component used to modify the expand panel size when expanded from the right */ public JPanel getRightDragger(){ /* This method is used by the UI to install proper borders */ if (rightDragger == null){ rightDragger = new JPanel(); } return rightDragger; } /** creates the shared title bar for all expanded panels */ protected DockViewTitleBar createTitleBar(){ return DockableContainerFactory.getFactory().createTitleBar(); //2007/01/08 //return new DockViewTitleBar(); } public DockViewTitleBar getTitleBar(){ return this.titleBar; } /** Creates the default borders for the expand panel */ public void resetBorders(){ Color shadow = UIManager.getColor("controlShadow"); Color highlight = UIManager.getColor("controlLtHighlight"); getTopDragger().setBorder(BorderFactory.createMatteBorder(1, 1, 0, 1, shadow)); getLeftDragger().setBorder(BorderFactory.createMatteBorder(1, 1, 1, 0, shadow)); getBottomDragger().setBorder(BorderFactory.createMatteBorder(0, 1, 1, 1, shadow)); getRightDragger().setBorder(BorderFactory.createMatteBorder(1, 0, 1, 1, shadow)); expandFromTopBorder = BorderFactory.createCompoundBorder( BorderFactory.createCompoundBorder( BorderFactory.createMatteBorder(1, 1, 0, 1, shadow), BorderFactory.createMatteBorder(1, 1, 1, 0, highlight)), BorderFactory.createEmptyBorder(2, 2, 2, 2) ); expandFromLeftBorder = BorderFactory.createCompoundBorder( BorderFactory.createCompoundBorder( BorderFactory.createMatteBorder(1, 1, 1, 0, shadow), BorderFactory.createMatteBorder(1, 1, 1, 1, highlight)), BorderFactory.createEmptyBorder(2, 2, 2, 2) ); expandFromBottomBorder = BorderFactory.createCompoundBorder( BorderFactory.createCompoundBorder( BorderFactory.createMatteBorder(0, 1, 1, 1, shadow), BorderFactory.createMatteBorder(1, 1, 1, 1, highlight)), BorderFactory.createEmptyBorder(2, 2, 2, 2) ); expandFromRightBorder = BorderFactory.createCompoundBorder( BorderFactory.createCompoundBorder( BorderFactory.createMatteBorder(1, 0, 1, 1, shadow), BorderFactory.createMatteBorder(1, 1, 1, 1, highlight)), BorderFactory.createEmptyBorder(2, 2, 2, 2) ); } /** Installs borders used to drag the expand panel around */ protected void initBorders(){ Dimension min = new Dimension(4, 4); topDragger.setVisible(false); topDragger.setPreferredSize(min); topDragger.setCursor(Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR)); DragListener topListener = new DragListener(DockingConstants.INT_HIDE_BOTTOM); topDragger.addMouseMotionListener(topListener); topDragger.addMouseListener(topListener); leftDragger.setVisible(false); leftDragger.setPreferredSize(min); leftDragger.setCursor(Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR)); DragListener leftListener = new DragListener(DockingConstants.INT_HIDE_RIGHT); leftDragger.addMouseMotionListener(leftListener); leftDragger.addMouseListener(leftListener); bottomDragger.setVisible(false); bottomDragger.setPreferredSize(min); bottomDragger.setCursor(Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR)); DragListener bottomListener = new DragListener(DockingConstants.INT_HIDE_TOP); bottomDragger.addMouseMotionListener(bottomListener); bottomDragger.addMouseListener(bottomListener); rightDragger.setVisible(false); rightDragger.setPreferredSize(min); rightDragger.setCursor(Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR)); DragListener rightListener = new DragListener(DockingConstants.INT_HIDE_LEFT); rightDragger.addMouseMotionListener(rightListener); rightDragger.addMouseListener(rightListener); if (DockingPreferences.isLightWeightUsageEnabled()){ add(topDragger, BorderLayout.NORTH); add(bottomDragger, BorderLayout.SOUTH); add(leftDragger, BorderLayout.WEST); add(rightDragger, BorderLayout.EAST); } else { if(!DockingPreferences.isSingleHeavyWeightComponent()){ heavyPanel.add(topDragger, BorderLayout.NORTH); heavyPanel.add(bottomDragger, BorderLayout.SOUTH); heavyPanel.add(leftDragger, BorderLayout.WEST); heavyPanel.add(rightDragger, BorderLayout.EAST); } } } private void initDockingFunctions(){ PropertyChangeListener listener = new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent e) { if (e.getPropertyName().equals(DockViewTitleBar.PROPERTY_AUTOHIDE)) { // from autohide to dock // remember values after autohide Dockable d = selectedButton.getDockable(); desk.setAutoHide(d, false); } else if (e.getPropertyName().equals(DockViewTitleBar.PROPERTY_CLOSED)) { Dockable d = selectedButton.getDockable(); collapse(); desk.close(d); } else if (e.getPropertyName().equals(DockViewTitleBar.PROPERTY_DRAGGED)){ // the user is starting a drag gesture : we must collapse ! collapse(); } else if (e.getPropertyName().equals(DockViewTitleBar.PROPERTY_FLOAT)){ Dockable d = selectedButton.getDockable(); collapse(); desk.setFloating(d, true); } } }; titleBar.addPropertyChangeListener(DockViewTitleBar.PROPERTY_AUTOHIDE, listener); titleBar.addPropertyChangeListener(DockViewTitleBar.PROPERTY_CLOSED, listener); titleBar.addPropertyChangeListener(DockViewTitleBar.PROPERTY_DRAGGED, listener); titleBar.addPropertyChangeListener(DockViewTitleBar.PROPERTY_FLOAT, listener); titleBar.installDocking(desk); desk.installDockableDragSource(titleBar); } /** Returns the component responsible for managing auto-expansion. * */ /* package protected */ ExpandControler getControler() { return controler; } /** Selects a button (may collapse a prevoiusly selected button) */ public void select(AutoHideButton btn){ if (selectedButton != null && selectedButton != btn){ collapse(); } selectedButton = btn; btn.setSelected(true); } private void restartCollapseTimer(){ // if (!DockingPreferences.isLightWeightUsageEnabled()){ if (canUseMouseInfo){ // not for 1.4 this.lastTimeMouseWasIn = System.currentTimeMillis(); collapseTimer.restart(); } } private void stopCollapseTimer(){ // if (!DockingPreferences.isLightWeightUsageEnabled()){ if (canUseMouseInfo){ // not for 1.4 collapseTimer.stop(); } } /** Expands the currently selected button */ public void expand(){ if (selectedButton == null){ return;//2007/01/10 //throw new IllegalStateException("No button selected for expansion"); } installComponent(); restartCollapseTimer(); setVisible(true); Rectangle bounds = desk.getBounds(); Dimension bestDimension = (Dimension)savedDimensions.get(selectedButton); if (bestDimension == null) { bestDimension = selectedButton.getDockable().getComponent().getPreferredSize(); switch (selectedButton.getZone()) { case DockingConstants.INT_HIDE_TOP: case DockingConstants.INT_HIDE_BOTTOM: if (bestDimension.height > bounds.height / 2) { bestDimension.height = bounds.height / 2; } break; case DockingConstants.INT_HIDE_LEFT: case DockingConstants.INT_HIDE_RIGHT: if (bestDimension.width > bounds.width / 2) { bestDimension.width = bounds.width / 2; } break; } } // outer insets (including autohide borders) Insets i = desk.getDockingPanelInsets(); // inner insets (of expandPanel : mouse grabbers etc..) Insets i2 = getComponentInsets(); switch (selectedButton.getZone()) { case DockingConstants.INT_HIDE_TOP: new ComponentAnimator(this, new Rectangle(i.left, i.top, bounds.width - i.left - i.right, 0), new Rectangle(i.left, i.top, bounds.width - i.left - i.right, bestDimension.height + i2.top + i2.bottom), AutoHidePolicy.getPolicy().getExpansionDuration()/1000f, animationControler); break; case DockingConstants.INT_HIDE_BOTTOM: new ComponentAnimator(this, new Rectangle(i.left, bounds.height - i.bottom, bounds.width - i.left - i.right, 0), new Rectangle(i.left, bounds.height - bestDimension.height - i.bottom - i2.top - i2.bottom, bounds.width - i.left - i.right, bestDimension.height +i2.top + i2.bottom), AutoHidePolicy.getPolicy().getExpansionDuration()/1000f, animationControler); break; case DockingConstants.INT_HIDE_LEFT: new ComponentAnimator(this, new Rectangle(i.left, i.top, 0, bounds.height - i.top - i.bottom), new Rectangle(i.left, i.top, bestDimension.width + i2.left + i2.right , bounds.height - i.top - i.bottom), AutoHidePolicy.getPolicy().getExpansionDuration()/1000f, animationControler); break; case DockingConstants.INT_HIDE_RIGHT: new ComponentAnimator(this, new Rectangle(bounds.width - i.right, i.top, 0, bounds.height - i.top - i.bottom), new Rectangle(bounds.width - bestDimension.width - i.right - i2.left - i2.right, i.top, bestDimension.width +i2.left + i2.right, bounds.height - i.top - i.bottom), AutoHidePolicy.getPolicy().getExpansionDuration()/1000f, animationControler); break; default : assert false; } firePropertyChange(PROPERTY_EXPANDED, false, true); } /** Removes a dockable (if it was the currently expanded one) */ public void remove(Dockable dockable){ Component comp = dockable.getComponent(); if (expandedComponent != null && expandedComponent == comp) { content.remove(expandedComponent); expandedComponent = null; } } private void installComponent(){ final Component comp = selectedButton.getDockable().getComponent(); if (expandedComponent != null){ if (expandedComponent != comp){ content.remove(expandedComponent); content.add(comp, BorderLayout.CENTER); //2005/12/08 back again in this order (JDIC workaround) installHeavyWeightParentIfNeeded(selectedButton.getDockable()); expandedComponent = comp; } } else { content.add(comp, BorderLayout.CENTER); installHeavyWeightParentIfNeeded(selectedButton.getDockable()); expandedComponent = comp; } /* // the workaround isn't needed anymore : we use the heavyweightTimer instead if (!DockingPreferences.isLightWeightUsageEnabled()){ // this is a workaround : mouse listener doesn't work properly // on AWT components (they grab the event even if they are 'under' // our mouse grabber. SwingUtilities.invokeLater(new Runnable(){ public void run(){ // heavyPanel.requestFocus(); comp.requestFocus(); } // by requesting focus, we can rely on the safer focusOwner property // and use it to collapse thi panel (see FocusCollapser code below) }); }*/ titleBar.setDockable(selectedButton.getDockable()); desk.installDockableDragSource(titleBar); switch (selectedButton.getZone()) { case DockingConstants.INT_HIDE_TOP: content.setBorder(expandFromTopBorder); bottomDragger.setVisible(true); // remove previous border if (lastDragger != null && lastDragger != bottomDragger) { lastDragger.setVisible(false); } lastDragger = bottomDragger; break; case DockingConstants.INT_HIDE_BOTTOM: content.setBorder(expandFromBottomBorder); topDragger.setVisible(true); if (lastDragger != null && lastDragger != topDragger) { lastDragger.setVisible(false); } lastDragger = topDragger; break; case DockingConstants.INT_HIDE_LEFT: content.setBorder(expandFromLeftBorder); rightDragger.setVisible(true); if (lastDragger != null && lastDragger != rightDragger) { lastDragger.setVisible(false); } lastDragger = rightDragger; break; case DockingConstants.INT_HIDE_RIGHT: content.setBorder(expandFromRightBorder); leftDragger.setVisible(true); if (lastDragger != null && lastDragger != leftDragger) { lastDragger.setVisible(false); } lastDragger = leftDragger; break; default : assert false; } revalidate(); repaint(); } /** Calculates the insets needed around the center component. * This is the sum of border sizes and bordercomponents sizes. * */ private Insets getComponentInsets(){ Insets i = getInsets(); // borders Insets i2 = content.getInsets(); i.top += i2.top; i.left += i2.left; i.bottom += i2.bottom; i.right += i2.right; if (topDragger.isVisible()){ i.top += topDragger.getHeight(); } i.top += titleBar.getHeight(); if (leftDragger.isVisible()){ i.left += leftDragger.getWidth(); } if (bottomDragger.isVisible()){ i.bottom += bottomDragger.getHeight(); } if (rightDragger.isVisible()){ i.right += rightDragger.getWidth(); } return i; } /** Collapse the expand panel (making it unvisible) */ public void collapse() { if (selectedButton != null){ savedDimensions.put(selectedButton, selectedButton.getDockable().getComponent().getSize()); selectedButton.setSelected(false); firePropertyChange(PROPERTY_EXPANDED, true, false); } selectedButton = null; setVisible(false); titleBar.closePopUp(); stopCollapseTimer(); if (!DockingPreferences.isLightWeightUsageEnabled()){ // we'd better repaint (ugly traces on linux) desk.repaint(); } } public void uninstallDocking(DockingDesktop desktop) { titleBar.uninstallDocking(desk); } public void installDocking(DockingDesktop desktop) { this.desk = desktop; initDockingFunctions(); } public Dockable getDockable() { if (selectedButton != null){ return selectedButton.getDockable(); } else { return null; } } public String getUIClassID() { return uiClassID; } /** Clears the state of this expand panel. *

* This is useful when re-installing a desktop from readXml (for example, * it resets dockable expand sizes) */ public void clear(){ // clear savedDimensions.clear(); } /** inner class that follows animations of expansion */ private class AnimationControler implements AnimationListener { public void animation(AnimationEvent e) { isExpanding = e.getState() != AnimationEvent.ANIMATION_END; if (e.getState() == AnimationEvent.ANIMATION_END){ SwingUtilities.invokeLater(new Runnable(){ public void run(){ content.repaint(); } }); } } } /** This class hides expansion implementation from API */ private class ExpandControler implements MouseListener, ActionListener, PropertyChangeListener{ /* temporary button : the next to be selected after a mouseEntered event and * triggered timer delay. */ private AutoHideButton mouseEnteredButton; /** used to avoid bad interactions between focus listeners and expand controler */ private boolean isUnderControl = false; public void mouseClicked(MouseEvent e) { // don't do anything during animation phase if (!isExpanding){ if (expansionTimer != null){ //2005/10/06 expansionTimer.stop(); } AutoHideButton clicked = (AutoHideButton) e.getSource(); if (selectedButton != clicked) { // we need to tell the focus listener not to manage focus while // this operation is occuring isUnderControl = true; select(clicked); // will trigger a focus change is DockingPreferences.isHeavuWeight SwingUtilities.invokeLater(new Runnable(){ public void run(){ expand(); isUnderControl = false; } }); } else { collapse(); } } } public void mouseEntered(MouseEvent e) { if (! isRolloverTimer) return; AutoHideButton btn = (AutoHideButton) e.getSource(); if (! btn.isSelected()){ // nothing more to do if selected if (expansionTimer != null){ expansionTimer.restart(); // 2005/10/06 } mouseEnteredButton = btn; } } public void mouseExited(MouseEvent e) { if (! isRolloverTimer) return; AutoHideButton btn = (AutoHideButton) e.getSource(); if (! btn.isSelected()){ // nothing more to do if selected expansionTimer.stop(); mouseEnteredButton = null; } } public void mousePressed(MouseEvent e) { } public void mouseReleased(MouseEvent e) { } public void propertyChange(PropertyChangeEvent e) { /* triggered by autohide policy change*/ if (e.getPropertyName().equals(AutoHidePolicy.PROPERTY_EXPAND_MODE)) { if (AutoHidePolicy.getPolicy().getExpandMode() == AutoHidePolicy.EXPAND_ON_ROLLOVER) { expansionTimer = new Timer(AutoHidePolicy.getPolicy(). getRolloverTriggerDelay(), this); isRolloverTimer = true; } else { expansionTimer.stop(); expansionTimer = null; isRolloverTimer = false; } } else if (e.getPropertyName().equals(AutoHidePolicy. PROPERTY_ROLLOVER_TRIGGER_DELAY)) { if (AutoHidePolicy.getPolicy().getExpandMode() == AutoHidePolicy.EXPAND_ON_ROLLOVER) { expansionTimer.setDelay( AutoHidePolicy.getPolicy().getRolloverTriggerDelay()); } } } public void actionPerformed(ActionEvent e) { // timer event : there is a button to expand assert mouseEnteredButton != null; isUnderControl = true; select(mouseEnteredButton); // will collapse the previous button SwingUtilities.invokeLater(new Runnable(){ public void run(){ expand(); isUnderControl = false; } }); } } private class DragListener implements MouseListener, MouseMotionListener{ /* inner class of expand panel*/ int zone; DragListener(int zone){ this.zone = zone; } public void mouseDragged(MouseEvent e) { /* implement the drag effect on expand panel : a single border * can be dragged (the one not overlapping the borders of the panel */ // new height/width (including borders) int newHeight, newWidth; // where are we on the desk ? Point p = SwingUtilities.convertPoint( (Component) e.getSource(), e.getPoint(), desk); Insets insets = getInsets(); Insets idesk = desk.getDockingPanelInsets(); switch (zone) { case DockingConstants.INT_HIDE_TOP: // drag from top to bottom : change the height of the panel newHeight = p.y - idesk.top + bottomDragger.getHeight()/2 + insets.bottom + insets.top; newHeight = Math.max(10, Math.min(newHeight, desk.getHeight())) ; // clip setSize(getWidth(), newHeight); invalidate(); validate(); repaint(); break; case DockingConstants.INT_HIDE_BOTTOM: newHeight = desk.getHeight() - idesk.bottom - p.y + topDragger.getHeight()/2 +insets.top + insets.bottom; int maxHeight = desk.getHeight() - topDragger.getHeight(); if (newHeight > maxHeight) { newHeight = maxHeight; } else if (newHeight < 10) { newHeight = 10; } Rectangle bounds = getBounds(); bounds.y = desk.getHeight() - idesk.bottom - newHeight; bounds.height = newHeight; setBounds(bounds); invalidate(); validate(); repaint(); break; case DockingConstants.INT_HIDE_LEFT: newWidth = p.x + rightDragger.getWidth()/2 - idesk.left + insets.right + insets.left; int maxWidth = desk.getWidth() - rightDragger.getWidth(); if (newWidth > maxWidth) { newWidth = maxWidth; } else if (newWidth < 10) { newWidth = 10; } setSize(newWidth,getHeight()); invalidate(); validate(); repaint(); break; case DockingConstants.INT_HIDE_RIGHT: newWidth = desk.getWidth()- idesk.right - p.x + leftDragger.getWidth()/2 + insets.left + insets.right; maxWidth = desk.getWidth() - leftDragger.getWidth(); if (newWidth > maxWidth) { newWidth = maxWidth; } else if (newWidth < 10) { newWidth = 10; } bounds = getBounds(); bounds.x = desk.getWidth() - idesk.right - newWidth; bounds.width = newWidth; setBounds(bounds); invalidate(); validate(); repaint(); break; } desk.repaint(); } public void mouseMoved(MouseEvent e) {} public void mouseClicked(MouseEvent e) {} public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) {} public void mousePressed(MouseEvent e) { shouldCollapse = false; // begining or drag } public void mouseReleased(MouseEvent e) { shouldCollapse = true; // end of drag } } private class FocusCollapser implements PropertyChangeListener { // focusOwner public void propertyChange(PropertyChangeEvent e) { if (!controler.isUnderControl){ // this is not a focus lost due to the expand controler Component c = (Component) e.getNewValue(); if (c != null && !AutoHideExpandPanel.this.isAncestorOf(c)) { // avoid collapsing when focus is given to a component which isn't a dockable if (DockingUtilities.findSingleDockableContainerAncestor(c) != null){ collapse(); } } } } } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/AutoHidePolicy.java0000644000175000017500000002225210573516346025773 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking; import java.beans.*; /** This class holds preferences on default autohiding behaviour. * * @see AutoHideButtonPanel * * @author Lilian Chamontin, vlsolutions. * @version 1.0 */ public class AutoHidePolicy { /** A constant for expanding a button on rollover */ public static final int EXPAND_ON_ROLLOVER = 0; /** A constant for expanding a button on click */ public static final int EXPAND_ON_CLICK = 1; /** a constant designing the bound property DEFAULT_HIDE_BORDER */ public static final String PROPERTY_DEFAULT_HIDE_BORDER = "defaultHideBorder"; /** a constant designing the bound property DEFAULT_GAP */ public static final String PROPERTY_DEFAULT_GAP = "defaultGap"; /** a constant designing the bound property EXPAND_MODE */ public static final String PROPERTY_EXPAND_MODE = "expandMode"; /** a constant designing the bound property ROLLOVER_TRIGGER_DELAY */ public static final String PROPERTY_ROLLOVER_TRIGGER_DELAY = "rolloverTriggerDelay"; /** a constant designing the bound property EXPANSION_DURATION */ public static final String PROPERTY_EXPANSION_DURATION = "expansionDuration"; private static AutoHidePolicy policy = new AutoHidePolicy(); /** where do we put the button at startup */ private DockingConstants.Hide defaultHideBorder = DockingConstants.HIDE_LEFT; /** pixels between two buttons */ private int defaultGap = 4; private int expandMode; // rollover / click private int rolloverTriggerDelay = 500; // wait before expansion (only for expandMode==ROLLOVER) private int expansionDuration = 300; // millis private PropertyChangeSupport propertySupport = new PropertyChangeSupport(this); private AutoHidePolicy() { } /** Updates the default hide border. *

* Default is AutoHideExpandPanel.LEFT; * * @param defaultHideBorder values taken from DockingConstants.HIDE_TOP, HIDE_LEFT, HIDE_BOTTOM, HIDE_RIGHT * */ public void setDefaultHideBorder(DockingConstants.Hide defaultHideBorder){ DockingConstants.Hide old = this.defaultHideBorder; this.defaultHideBorder = defaultHideBorder; propertySupport.firePropertyChange(PROPERTY_DEFAULT_HIDE_BORDER, old, defaultHideBorder); } /** Returns the default hide border (used when not specified in a DockKey)*/ public DockingConstants.Hide getDefaultHideBorder(){ return defaultHideBorder; } /** Returns the default gap between border components */ public int getDefaultGap(){ return defaultGap; } /** Updates the gap (in pixels) between auto-hide buttons*/ public void setDefaultGap(int gap){ int old = this.defaultGap; this.defaultGap = gap; propertySupport.firePropertyChange(PROPERTY_DEFAULT_GAP, old, gap); } /** Returns the singleton instance of this class */ public static AutoHidePolicy getPolicy(){ return policy; } /** Returns the expand mode in use. * @return EXPAND_ON_ROLLOVER or EXPAND_ON_CLICK * */ public int getExpandMode(){ return expandMode; } /** Updates the expand mode. * @param expandMode legal values are EXPAND_ON_ROLLOVER or EXPAND_ON_CLICK * */ public void setExpandMode(int expandMode){ int old = this.expandMode; this.expandMode = expandMode; propertySupport.firePropertyChange(PROPERTY_EXPAND_MODE, old, expandMode); } /** Returns the rollover trigger delay (in millis) * * */ public int getRolloverTriggerDelay(){ return rolloverTriggerDelay; } /** Updates the rollover trigger delay * @param delay delay in millis before expanding a Dockable */ public void setRolloverTriggerDelay(int delay){ int old = this.rolloverTriggerDelay; this.rolloverTriggerDelay = delay; propertySupport.firePropertyChange(PROPERTY_ROLLOVER_TRIGGER_DELAY, old, delay); } /** Returns the expansion duration (in millis) */ public int getExpansionDuration(){ return expansionDuration; } /** Updates the expansion duration (time in millis) */ public void setExpansionDuration(int millis){ int old = expansionDuration; this.expansionDuration = millis; propertySupport.firePropertyChange(PROPERTY_EXPANSION_DURATION, old, millis); } /** Hook for property change notification */ public void addPropertyChangeListener(PropertyChangeListener listener) { propertySupport.addPropertyChangeListener(listener); } /** Hook for property change notification */ public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { propertySupport.addPropertyChangeListener(propertyName, listener); } /** Remove a property change notification */ public void removePropertyChangeListener(PropertyChangeListener listener) { propertySupport.removePropertyChangeListener(listener); } /** Remove a property change notification */ public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { propertySupport.removePropertyChangeListener(propertyName, listener); } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/BorderSplitter.java0000644000175000017500000003040010573516346026047 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking; import com.vlsolutions.swing.docking.event.DockDropEvent; import com.vlsolutions.swing.docking.event.DockDragEvent; import java.awt.geom.Rectangle2D; import java.awt.*; import com.vlsolutions.swing.docking.event.*; /** An utility class used to delegate the border drag/drop scanning for docking ( * since the same code is used in many DockDropReceivers). *

* This class is only meant for API Extenders. *

* Taking a DockDragEvent or DockDropEvent, check if mouse is near of one border. * If so, accepts the drag or drop operation. * * @author Lilian Chamontin, vlsolutions. * @version 1.0 * @update 2005/10/21 Lilian Chamontin : updated the shape to show real size of drop (and not 20 pixeles width/height) * @update 2005/11/14 Lilian Chamontin : added support for drag and drop of a whole tabbed container * @update 2005/12/08 Lilian Chamontin : fixed a bug when dropping into itself */ public class BorderSplitter { Component delegator; public BorderSplitter(Component delegator) { this.delegator = delegator; } public void processDockableDrag(DockDragEvent e){ scanDrop(e, false); } public void processDockableDrop(DockDropEvent e){ scanDrop(e, true); } /** This method should be overriden if the delegator doesn't belong to the * docking containment hierarchy after drop acceptance. *

Here is a case : *

* *

* Then, tabpane will be replaced by a simple DockableContainer on drop acceptance * (because only one tab left). *

* And DockingDesktop.splitContainer(Component base, Split position) cannot be * called with tabpane as "base" (instead, it should be called with the replacer of * tabpane, or use the other split method which takes a dockable as base. * * * */ public void split(DockDropEvent event, Container draggedContainer, DockingConstants.Split position){ /* standard splitting */ // event.getDesktop().splitComponent(delegator, event.getDragSource().getDockable(), // position); event.getDesktop().splitComponent(delegator, draggedContainer, position); //2005/11/14 } private void acceptSplit(DockDropEvent event, DockingConstants.Split position){ Container container = event.getDragSource().getDockableContainer(); Dockable dockable = event.getDragSource().getDockable();//2005/12/08 TabbedDockableContainer tabAncestor = DockingUtilities.findTabbedDockableContainer(dockable); ( (DockDropEvent) event).acceptDrop(); if (container instanceof TabbedDockableContainer){ split(event, container, position); } else { if (tabAncestor != null && tabAncestor.getTabCount() == 1 && tabAncestor == delegator){ // we have detected a dropping onto itself : // the drop gesture comes from the tabAncestor (as it's given by the drag source) // and translates into a border split // if only one tab remains, that means the tabAncestor is no longer useful and // so we now need to remove that tab and replace it by a standard singledockable // which is done by the standard desktop "split" public method. Dockable remainingDockable = tabAncestor.getDockableAt(0); event.getDesktop().split( remainingDockable, // the only remaining dockable dockable, position); } else { // standard dropping, just use the internal API to relayout the desktop. event.getDesktop().splitComponent(delegator, dockable, position); } } } /** Accept the drag gesture and setup the docking action event associated to it */ private void acceptDragSplit(DockDragEvent event, DockingConstants.Split position, Shape shape){ Container container = event.getDragSource().getDockableContainer(); Dockable dockable = event.getDragSource().getDockable();//2005/12/08 TabbedDockableContainer tabAncestor = DockingUtilities.findTabbedDockableContainer(dockable); int initialState = dockable.getDockKey().getDockableState(); int borderSpliterState = DockingUtilities.getDockableStateFromHierarchy(delegator); if (container instanceof TabbedDockableContainer){ event.setDockingAction(new DockingActionSplitComponentEvent(event.getDesktop(), dockable, initialState, borderSpliterState, container, position, 0.5f)); } else { if (tabAncestor != null && tabAncestor.getTabCount() == 1 && tabAncestor == delegator){ // we have detected a dropping onto itself : // the drop gesture comes from the tabAncestor (as it's given by the drag source) // and translates into a border split // if only one tab remains, that means the tabAncestor is no longer useful and // so we now need to remove that tab and replace it by a standard singledockable // which is done by the standard desktop "split" public method. Dockable remainingDockable = tabAncestor.getDockableAt(0); event.setDockingAction(new DockingActionSplitDockableEvent(event.getDesktop(), dockable, initialState, borderSpliterState, remainingDockable, position, 0.5f)); } else { // standard dropping, just use the internal API to relayout the desktop. event.setDockingAction(new DockingActionSplitComponentEvent(event.getDesktop(), dockable, initialState, borderSpliterState, delegator, position, 0.5f)); } } event.acceptDrag(shape); } private void scanDrop(DockEvent event, boolean drop){ Point p = event.getMouseEvent().getPoint(); Dimension size = delegator.getSize(); int distTop = p.y; int distLeft = p.x; int min = Math.min(distTop, distLeft); int distRight = size.width - p.x; min = Math.min(min, distRight); int distBottom = size.height - p.y; min = Math.min(min, distBottom); Dimension draggedSize = null; DockableDragSource source = event.getDragSource(); // the drag size is the one of the parent dockable container //draggedSize = dragged.getComponent().getParent().getSize(); draggedSize = source.getDockableContainer().getSize(); int bestHeight = (int)Math.min(draggedSize.height , size.height * 0.5); int bestWidth = (int)Math.min(draggedSize.width , size.width * 0.5); if (min == distTop && min < delegator.getHeight()/4) { // dock on top if (drop) { acceptSplit((DockDropEvent) event, DockingConstants.SPLIT_TOP); } else { Rectangle2D r2d = new Rectangle2D.Float(0, 0, size.width, bestHeight); acceptDragSplit((DockDragEvent) event, DockingConstants.SPLIT_TOP, r2d); } } else if (min == distLeft && min < delegator.getWidth()/4) { if (drop) { acceptSplit((DockDropEvent) event, DockingConstants.SPLIT_LEFT); } else { Rectangle2D r2d = new Rectangle2D.Float(0, 0, bestWidth, size.height); acceptDragSplit((DockDragEvent) event, DockingConstants.SPLIT_LEFT, r2d); } } else if (min == distBottom && min < delegator.getHeight()/4) { if (drop) { acceptSplit((DockDropEvent) event, DockingConstants.SPLIT_BOTTOM); } else { Rectangle2D r2d = new Rectangle2D.Float(0, size.height - bestHeight, //20, size.width, bestHeight); acceptDragSplit((DockDragEvent) event, DockingConstants.SPLIT_BOTTOM, r2d); } } else if (min == distRight && min < delegator.getWidth()/4){ // right if (drop) { acceptSplit((DockDropEvent) event, DockingConstants.SPLIT_RIGHT); } else { Rectangle2D r2d = new Rectangle2D.Float( size.width - bestWidth, 0, bestWidth, size.height); acceptDragSplit((DockDragEvent) event, DockingConstants.SPLIT_RIGHT, r2d); } } } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/CompoundDockable.java0000644000175000017500000001377310573516346026332 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking; import java.awt.Component; /** Describes a Dockable that can contain sub-dockables. *

* This class allows dockable nesting, with full support for workspace save and restore. *

* Currently this class is associated to a CompoundDockingPanel component : you * insert dockables into it with an initial addDockable(CompoundDockable) invocation from DockingDesktop, * and further dockables with split/createTab calls. *

* Example : *

 *   DockingDesktop desk = ...
 *   desk.addDockable(dockable1);
 *   desk.split(dockable1, dockable2, DockingConstants.SPLIT_RIGHT);
 *   // now let's add a compound dockable
 *   CompoundDockable compound = new CompoundDockable(new DockKey("Compound!"));
 *   desk.split(dockable1, compound);
 *   // and add a tab into it
 *   desk.addDockable(compound, dockable3); // initial nesting : new API call
 *   desk.createTab(dockable3, dockable4, 1); // a tab, using standard API
 * 
*

* CompoundDockables are displayed as SingleDockableContainers (with a title bar). Don't * forget to properly initialize the DockKey of this dockable to have it well presented on * screen (name, tooltip, icon). * * @author Lilian Chamontin, VLSolutions * @since 2.1 */ public class CompoundDockable implements Dockable { private CompoundDockingPanel panel = new CompoundDockingPanel(this); private DockKey key; /** Constructs a new CompoundDockable with a given key */ public CompoundDockable(DockKey key){ this.key = key; } /** Returns the key used to describe this dockable */ public DockKey getDockKey() { return key; } /** Returns the component used by this dockable. * *

* Implementation note : this method always returns a CompoundDockingPanel. * */ public final Component getComponent() { return panel; } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/CompoundDockingPanel.java0000644000175000017500000001664610573516346027166 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking; import com.vlsolutions.swing.docking.event.DockDragEvent; import com.vlsolutions.swing.docking.event.DockDropEvent; import com.vlsolutions.swing.docking.event.DockEvent; import com.vlsolutions.swing.docking.event.DockingActionAddDockableEvent; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Point; import java.awt.Rectangle; import java.awt.event.ContainerEvent; import java.awt.event.ContainerListener; import java.awt.geom.Rectangle2D; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import javax.swing.JComponent; import javax.swing.JPanel; import javax.swing.event.AncestorEvent; import javax.swing.event.AncestorListener; /** A specialized container used to nest dockables inside that sub-part of the * desktop. *

* This component is used by the API (as the associate component of a CompoundDockable) * and shouldn't be used outside this context. * * @author Lilian Chamontin, VLSolutions * @since 2.1 * @see CompoundDockable */ public class CompoundDockingPanel extends JPanel implements DockDropReceiver { private CompoundDockable dockable; /** Constructs a new CompoundDockingPanel, for a given dockable */ public CompoundDockingPanel(CompoundDockable dockable) { setLayout(new BorderLayout()); this.dockable = dockable; } /** act the same as a splitContainer : allow drop on the borders*/ public void processDockableDrag(DockDragEvent event) { scanContainer(event, false); } public void processDockableDrop(DockDropEvent event) { scanContainer(event, true); } private void acceptDrop(DockEvent event){ ( (DockDropEvent) event).acceptDrop(); Dockable d = event.getDragSource().getDockable(); DockableContainer dockableContainer = DockableContainerFactory.getFactory(). createDockableContainer(d, DockableContainerFactory.PARENT_DESKTOP); dockableContainer.installDocking(event.getDesktop()); add((JComponent)dockableContainer, BorderLayout.CENTER); } private void scanContainer(DockEvent event, boolean drop) { // reject operation if the source is an ancestor of this component if (event.getDragSource().getDockableContainer().isAncestorOf(this)){ // this is possible for compound containers (as they contain sub-dockables) // in that case, you cannnot drop a compound into one of its children // 2007/01/08 if (drop){ ((DockDropEvent) event).rejectDrop(); } else { ((DockDragEvent) event).delegateDrag(); } return; } Point p = event.getMouseEvent().getPoint(); Rectangle compBounds = getBounds(); Dockable dragged = event.getDragSource().getDockable(); int initialState = dragged.getDockKey().getDockableState(); int nextState = dockable.getDockKey().getDockableState(); event.setDockingAction(new DockingActionAddDockableEvent(event.getDesktop(), dragged, initialState, nextState, this)); if (drop) { acceptDrop(event); } else { Rectangle2D r2d = new Rectangle2D.Float(0, 0, compBounds.width, compBounds.height); ( (DockDragEvent) event).acceptDrag(r2d); } } /** Returns the compound dockable this container is for */ public CompoundDockable getDockable() { return dockable; } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/DefaultDockableContainerFactory.java0000644000175000017500000001542310573516346031317 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking; import java.awt.Dialog; import java.awt.Frame; import java.awt.Window; /** Default implementation of the DockableContainerFactory. *

* Uses DockView as a SingleDockableContainer, * and DockTabbedPane as a TabbedDockableContainer *

* Note : the API has changed between VLDocking 1.1 and 2.0 : the createDockableContainer * now uses a second parameter to specify the context of the container creation. * * @author Lilian Chamontin, vlsolutions. * @version 2.0 */ public class DefaultDockableContainerFactory extends DockableContainerFactory { public DefaultDockableContainerFactory() { } /** Returns the component used to modify the expand panel size when expanded from the top. * This implementation uses the following components : *

* *@see DockView *@see TabbedDockView *@see MaximizedDockView *@see DetachedDockView */ public SingleDockableContainer createDockableContainer(Dockable dockable, int parentType) { switch (parentType){ case PARENT_TABBED_CONTAINER: return new TabbedDockView(dockable); case PARENT_DESKTOP: return new MaximizedDockView(dockable); case PARENT_SPLIT_CONTAINER: return new DockView(dockable); case PARENT_DETACHED_WINDOW: return new DetachedDockView(dockable); default : throw new RuntimeException("Wrong dockable container type"); } } /** Returns the container used for tabbed docking. *

* Current implementation uses the DockTabbedPane class. * * @see DockTabbedPane */ public TabbedDockableContainer createTabbedDockableContainer() { return new DockTabbedPane(); } /** This method is called when a dockable is detached from the DockingDesktop and put * in the FLOATING state. *

* The floating container must be an instanceof Dialog or Window. */ public FloatingDockableContainer createFloatingDockableContainer(Window owner){ if (owner instanceof Dialog){ return new FloatingDialog((Dialog)owner); } else { return new FloatingDialog((Frame)owner); } } /** This implementation of the factory method return a default DockViewTitleBar * object. *@since 2.1.3 */ public DockViewTitleBar createTitleBar() { return new DockViewTitleBar(); } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/DetachedDockView.java0000644000175000017500000001745710573516346026261 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking; import com.vlsolutions.swing.docking.event.DockDragEvent; import com.vlsolutions.swing.docking.event.DockDropEvent; import com.vlsolutions.swing.docking.event.DockEvent; import com.vlsolutions.swing.docking.event.DockingActionCreateTabEvent; import java.awt.Rectangle; import java.awt.geom.GeneralPath; import java.awt.geom.Rectangle2D; /** A DockView suitable for detached dockables (in their own window). * * @see DockView * * @author Lilian Chamontin, VLSolutions * @since 2.0 */ public class DetachedDockView extends DockView { private static final String uiClassID = "DetachedDockViewUI"; public DetachedDockView(Dockable dockable) { super(dockable); } /** {@inheritDoc} * @since 2.0 */ public String getUIClassID() { return uiClassID; } /* common method for drag && drop, overriden from DockView to only allow tabbed drops */ protected void scanDrop(DockEvent event, boolean drop){ if (getParent() instanceof TabbedDockableContainer){ // cannot nest DockTabbedPanes if (drop){ ((DockDropEvent) event).rejectDrop(); } else { ((DockDragEvent) event).delegateDrag(); } return; } if (event.getDragSource().getDockable() == dockable) { // cannot drop onto itself if (drop){ ((DockDropEvent) event).rejectDrop(); } else { ((DockDragEvent) event).rejectDrag(); } return; } // The dockview isn't contained inside a tabbedpane, // there is only one possible option : to create an tab if (event.getDragSource().getDockableContainer() instanceof TabbedDockableContainer) { // but you cannot drop a whole tab container into a detached view if (drop){ ((DockDropEvent) event).rejectDrop(); } else { ((DockDragEvent) event).rejectDrag(); } return; } Rectangle bounds = getBounds(); // not on the borders : we should create a new tab // reject if key groups aren't compatible DockGroup thisGroup = dockable.getDockKey().getDockGroup(); DockGroup dragGroup = event.getDragSource().getDockable().getDockKey().getDockGroup(); if (!DockGroup.areGroupsCompatible( thisGroup, dragGroup)){ if (drop){ ((DockDropEvent) event).rejectDrop(); } else { ((DockDragEvent) event).rejectDrag(); } return; } Dockable d = event.getDragSource().getDockable(); int dockableState = d.getDockKey().getDockableState(); int viewState = dockable.getDockKey().getDockableState(); if (drop){ event.setDockingAction(new DockingActionCreateTabEvent(event.getDesktop(), d, dockableState, viewState, dockable, 0)); ((DockDropEvent) event).acceptDrop(false); // don't remove the floatable : we have to find it's current position desktop.createTab(dockable, event.getDragSource().getDockable(), 0, true); } else { Rectangle2D r2d = new Rectangle2D.Float(bounds.x, bounds.y, bounds.width, bounds.height); event.setDockingAction(new DockingActionCreateTabEvent(event.getDesktop(), d, dockableState, viewState, dockable, 0)); if (r2d.equals(lastDropShape)) { // optimized shape caching ( (DockDragEvent) event).acceptDrag(lastDropGeneralPath); } else { // draw a 'tabbed pane shape' GeneralPath path = buildPathForTab(bounds);; lastDropShape = r2d; lastDropGeneralPath = path; ( (DockDragEvent) event).acceptDrag(lastDropGeneralPath); } } } /** {@inheritDoc} */ public String toString(){ return "DetachedDockView of " + dockable.getDockKey(); } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/DockDropReceiver.java0000644000175000017500000001424410573516346026305 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking; import java.awt.*; import com.vlsolutions.swing.docking.event.*; /** An interface implemented by components that can accept docking action with mouse drag and drop. *

* This interface is used by API Extenders to create new kind of drop receivers. *

* The DockDropReceiver is responsible for the Drag and Drop gesture recognition of * a docking movement. When a user starts a drag gesture over a {@link DockableDragSource}, * the DockingDesktop scans its containment hierarchy (under the mouse pointer), looking * for DockDropReceivers. If one is found, it is asked for drag or drop processing. *

* The receiver can reject a drag, or display a shape explaining to the user how a * drop of the component would affect the global layout. * * * @see DockableDragSource * * @author Lilian Chamontin, vlsolutions. * @version 1.0 * */ public interface DockDropReceiver { /** The component is notified of a drag operation. * *

* This method is used to give a visual clue of dropping capability * (for example, mouse cursor change, painting a shadow of future component position) * * *

* These clues are transmitted via the event's methods. * * @see DockDragEvent * @see DockDropEvent * * */ public void processDockableDrag(DockDragEvent event); /** The component is requested to perform a docking drop action. *

* This method is called only after a successful {@link #processDockableDrag(DockDragEvent)} *

* The parameters provided for the drop are the same than those of the last drag * (in order to avoid an allowed last drag followed by a rejected drop). *

* On event acceptation ( {@link DockDropEvent#acceptDrop() } , the source component * will be removed from its container, so the DropReceiver must add the * component to its own hierarchy otherwise * the component would be lost (from a user's point of view). * */ public void processDockableDrop(DockDropEvent event) ; } vldocking_2.1.4/src/com/vlsolutions/swing/docking/DockGroup.java0000644000175000017500000001762510573516346025016 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking; import java.util.ArrayList; import javax.swing.Action; /** This class describes a logical group of Dockables. *

* When a dockable is associated to a DockGroup (via its DockKey) drag and drop operations * are limited to dockables of the same group (or new location) or compatible group (a group with * a common ancestor see {@link #isCompatibleGroup(DockGroup)} ). *

* It becomes easy to develop, for example, and MDI program : all documents are given the same * DockGroup, and other dockable are given another group so they don't mess with each other. *

* The DockGroups can be nested to allow some mixing (for example, an editor application can consist of * 4 groups : "Formaters" and "Files" the parent of "TextFiles" and "HTMLfile". In that case, * Textfiles and Htmlfiles can be part of tha same tabbed container whereas Formaters are kept outside. * * * @see DockKey#setDockGroup(DockGroup) * @author Lilian Chamontin, VLSolutions * @since 2.0 */ public class DockGroup { /** The optional parent of this group */ private DockGroup parent; /** internal name for comparisons */ private String name; /** Constructs a new dockgroup with a given name. *

Note that names must be unique (this feature is not controlled by the framework) * through all DockGroups. */ public DockGroup(String name) { this.name = name; } /** Constructs a new dockgroup with a given name and a parent group. *

Note that names must be unique (this feature is not controlled by the framework) * through all DockGroups. */ public DockGroup(String name, DockGroup parent) { this.name = name; this.parent = parent; } /** returns the parent of this group (may be null) */ public DockGroup getParent(){ return parent; } /** Updates the parent of this group */ public void setParent(DockGroup parent){ this.parent = parent; } /** returns the name of this group (which is used as an internal key) */ public String getName(){ return name; } /** overriden for storage/comparisons with the "name" property */ public boolean equals(Object o){ return o != null && o instanceof DockGroup && ((DockGroup)o).name.equals(name); } /** overriden for storage/comparisons with the "name" property */ public int hashCode(){ return name.hashCode(); } /** returns true if this group is the ancestor of group g. * To be an ancestor, this group must be either equel to g, or to one of g's parents chain. */ public boolean isAncestorOf(DockGroup g){ if (this.equals(g)){ return true; } else { DockGroup parent = g.parent; while (parent != null){ if (this.equals(parent)){ return true; } else { parent = parent.parent; } } } return false; } /** returns true is this group is compatible with the given parameter. *

* two groups are compatible if they share the same ancestor or if one is the * ancestor of the other. *

* When compatibility is found, dockables of those groups can be docked in * the same tab container. */ public boolean isCompatibleGroup(DockGroup g){ if (g == null) return false; if (this.equals(g)){ return true; } else if (this.isAncestorOf(g)) { return true; } else if (g.isAncestorOf(this)){ return true; } else if (parent != null){ return parent.isCompatibleGroup(g.parent); } else { return false; } } /** convenience method to check compatibility between groups */ public static boolean areGroupsCompatible(DockGroup g1, DockGroup g2){ if (g1 == null){ return g2 == null; } else if (g2 == null){ return g1 == null; } else { return g1.isCompatibleGroup(g2); } } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/DockKey.java0000644000175000017500000004424210573516346024445 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking; import javax.swing.*; import java.beans.*; import java.util.HashMap; /** * Provides a unique identification for a Dockable and runtime properties, like icon, name, * tooltip, preferred audohide-zone... * *

* As it is the object which identifies uniquely a user Dockable component, * it should be associated with one and only one Dockable. *

* The unique key used for equals() comparison is the dockKey property, * other properties can be shared by a set of DockKey (for example, * you can share an icon, or even a display name between * dockable Components). * *

* Another usage is the decoration of a dockable container, providing informations * such as its name, tooltip or icon. *

* Properties of a DockKey are listened to by the docking framework, so a change * of name or icon is reflected on the GUI without further programming. * * @author Lilian Chamontin, vlsolutions. * @version 1.0 * * @update 2006/12/01 Lilian Chamontin : added client property support * */ public class DockKey { /** Key identifying a change in the tooltip property */ public static final String PROPERTY_TOOLTIP = "tooltip"; /** Key identifying a change in the name property */ public static final String PROPERTY_NAME = "name"; /** Key identifying a change in the tabname property (title used by tabbed containers) */ public static final String PROPERTY_TAB_NAME = "tabName"; /** * Key identifying a change in the dockKey property */ public static final String PROPERTY_DOCKKEY = "dockKey"; /** Key identifying a change in the icon property */ public static final String PROPERTY_ICON = "icon"; /** Key identifying a change in the autohideEnabled property */ public static final String PROPERTY_AUTOHIDEABLE = "autohide"; /** Key identifying a change in the closeEnabled property */ public static final String PROPERTY_CLOSEABLE = "close"; /** Key identifying a change in the maximizedEnabled property */ public static final String PROPERTY_MAXIMIZABLE = "maximizable"; /** Key identifying a change in the notification property */ public static final String PROPERTY_NOTIFICATION = "notification"; /** Key identifying a change in the floatableEnabled property */ public static final String PROPERTY_FLOATABLE = "floatable"; /** * Key identifying a change in the dockable dockableState */ public static final String PROPERTY_DOCKABLE_STATE = "dockablestate"; private String dockKey; private String name; /** new as 2.1 : the tab name property is used to display the dockable title when tabbed*/ private String tabName; private String tooltip; private Icon icon; private DockingConstants.Hide autoHideBorder ; private boolean isAutoHideEnabled = true; private boolean isCloseEnabled = true; private boolean isMaximizeEnabled = true; private boolean isFloatEnabled = false; // for compatiblity with version 1.1 /** resize weight of the dockable, this is not a bound property and should be set * during initialization. */ private float resizeWeight = 0f; private boolean notification = false; /** additional client properties * @since 2.1.2 */ private HashMap clientProperties = null; /** * Current visibility dockableState of the dockable (DockableState.STATE_CLOSED, STATE_AUTO_HIDE, STATE_DOCKED, STATE_MAXIMIZED, * STATE_FLOATING) */ private int dockableState = DockableState.STATE_CLOSED; // these are not bound properties private DockGroup dockGroup; private DockableActionCustomizer actionCustomizer; private transient PropertyChangeSupport propertySupport = new PropertyChangeSupport(this); /** * JavaBeans constructor : If used, also think to set the dockKey property. */ public DockKey() { } /** * Constructs a DockKey with dockKey (unique key) and name set to the same value */ public DockKey(String dockKey){ this(dockKey, dockKey, null, null, null); } /** * Constructs a DockKey with dockKey (unique key) and a displayed name */ public DockKey(String dockKey, String name){ this(dockKey, name, null, null, null); } /** * Constructs a DockKey with dockKey (unique key), a displayed name and a tooltip */ public DockKey(String dockKey, String name, String tooltip){ this(dockKey, name, tooltip, null, null); } /** * Constructs a DockKey with dockKey (unique key), a displayed name, a tooltip and * an icon. */ public DockKey(String dockKey, String name, String tooltip, Icon icon){ this(dockKey, name, tooltip, icon, null); } /** * Constructs a DockKey with dockKey (unique key), a displayed name, a tooltip, an icon * and a default autohide border. */ public DockKey(String dockKey, String name, String tooltip, Icon icon, DockingConstants.Hide hideBorder){ this.dockKey = dockKey; this.name = name; this.tooltip = tooltip; this.icon = icon; this.autoHideBorder = hideBorder; } /** Hook for property change notification */ public void addPropertyChangeListener(PropertyChangeListener listener){ propertySupport.addPropertyChangeListener(listener); } /** Remove a property change notification */ public void removePropertyChangeListener(PropertyChangeListener listener){ propertySupport.removePropertyChangeListener(listener); } /** Returns the icon displayed in title bars */ public Icon getIcon() { return icon; } /** Returns the name (or title) displayed in title bars */ public String getName() { return name; } /** Returns the tooltip associated to the title bar */ public String getTooltip() { if (tooltip == null) { return name; } return tooltip; } /** Returns the unique id designating the user component. *

* Note : This used to be the getDockName prior version 2.0. It has been renamed * to clarify the concept (there was a naming problem between getName() and getDockName() * */ public String getKey() { return dockKey; } /** Updates the tooltip property. *

PropertyListeners are notified of that change * */ public void setTooltip(String tooltip) { String old = this.tooltip; this.tooltip = tooltip; propertySupport.firePropertyChange(PROPERTY_TOOLTIP, old, tooltip); } /** Updates the name property. * The name property is used by dockable container headers to associate a title with a dockable. *

PropertyListeners are notified of that change * */ public void setName(String name) { String old = this.name; this.name = name; propertySupport.firePropertyChange(PROPERTY_NAME, old, name); } /** Returns the tab name (or tab title) displayed when the component is contained into a tabbed container. */ public String getTabName() { return tabName; } /** Updates the tabname property. * This property is used by tabbed containers to display a shorter version of the title of this dockable. *

* Default value is null, meaning the name *

* PropertyListeners are notified of that change * *@since 2.1 * */ public void setTabName(String tabName) { String old = this.tabName; this.tabName = tabName; propertySupport.firePropertyChange(PROPERTY_TAB_NAME, old, tabName); } /** Updates the icon property. *

* PropertyListeners are notified of that change */ public void setIcon(Icon icon) { Icon old = this.icon; this.icon = icon; propertySupport.firePropertyChange(PROPERTY_ICON, old, icon); } /** * Updates the dockKey property. *

* Although PropertyListeners are notified of that change, * it is not recommended to change dynamicaly the dockKey property, as it is heavily used in * the docking framework to identify dockable components. *

* Note : This used to be the getDockName prior version 2.0. It has been renamed * to clarify the concept (there was a naming problem between getName() and getDockName() */ public void setKey(String dockKey) { String old = this.dockKey; this.dockKey = dockKey; propertySupport.firePropertyChange(PROPERTY_DOCKKEY, old, dockKey); } /** @see #getKey() * @deprecated use getKey instead */ public String getDockName(){ return getKey(); } /** @see #setKey(String) * @deprecated use setKey instead */ public void setDockName(String name){ setKey(name); } /** Returns the autohide border of this dockable, or null if not set*/ public DockingConstants.Hide getAutoHideBorder(){ return autoHideBorder; } /** Updates the autohide border property */ public void setAutoHideBorder(DockingConstants.Hide border){ this.autoHideBorder = border; } /** Returns try if autohiding is enabled */ public boolean isAutoHideEnabled(){ return isAutoHideEnabled; } /** Updates the autohideEnabled propety. *

* PropertyListeners are notified of that change * */ public void setAutoHideEnabled(boolean enabled) { boolean old = this.isAutoHideEnabled; this.isAutoHideEnabled = enabled; propertySupport.firePropertyChange(PROPERTY_AUTOHIDEABLE, old, enabled); } /** Returns true if this dockable can be closed */ public boolean isCloseEnabled(){ return isCloseEnabled; } /** Updates the closeEnabled propety. *

PropertyListeners are notified of that change * */ public void setCloseEnabled(boolean enabled) { boolean old = this.isCloseEnabled; this.isCloseEnabled = enabled; propertySupport.firePropertyChange(PROPERTY_CLOSEABLE, old, enabled); } /** Returns true if this dockable can be maximized */ public boolean isMaximizeEnabled(){ return isMaximizeEnabled; } /** Updates the maximizeEnabled propety. *

PropertyListeners are notified of that change * */ public void setMaximizeEnabled(boolean enabled) { boolean old = this.isMaximizeEnabled; this.isMaximizeEnabled = enabled; propertySupport.firePropertyChange(PROPERTY_MAXIMIZABLE, old, enabled); } /** Returns true if this dockable can be detached from its desktop */ public boolean isFloatEnabled(){ return isFloatEnabled; } /** Updates the floatEnabled propety. *

PropertyListeners are notified of that change * */ public void setFloatEnabled(boolean enabled) { boolean old = this.isFloatEnabled; this.isFloatEnabled = enabled; propertySupport.firePropertyChange(PROPERTY_FLOATABLE, old, enabled); } /** Returns true is a notification has been set. *

default notification is making title bars blink. * */ public boolean isNotification(){ return notification; } /** Updates the notification propety. Notification results in * a visual change of the dockable in order to attract attention from the * user to this dockable. * *

PropertyListeners are notified of that change. * */ public void setNotification(boolean notification) { boolean old = this.notification; this.notification = notification; propertySupport.firePropertyChange(PROPERTY_NOTIFICATION, old, notification); } /** Overriden for Map storage needs */ public int hashCode(){ return dockKey.hashCode(); } /** Overriden for Map storage needs */ public boolean equals(Object o){ return o instanceof DockKey && dockKey.equals(((DockKey)o).dockKey); } public String toString(){ return "DockKey[" + name +']'; } /** Returns the action customizer associated to this dockkey (may return null) * */ public DockableActionCustomizer getActionCustomizer(){ return actionCustomizer; } /** Updates the action customizer of this dockable * */ public void setActionCustomizer(DockableActionCustomizer actionCustomizer){ this.actionCustomizer = actionCustomizer; } /** Updates the dockGroup of this dockable. */ public void setDockGroup(DockGroup group){ this.dockGroup = group; } /** returns the dockGroup of this dockable */ public DockGroup getDockGroup(){ return this.dockGroup; } /** * returns the current visible dockableState of the dockable (see DockableState.STATE_ for enumaration values) * @see DockableState */ public int getDockableState(){ return dockableState; } /** updates the dockableState property. *

* Warning : do not call this method, it is for the sole use of the DockingDesktop API. * @see DockableState */ public void setDockableState(int dockableState){ int old = this.dockableState; this.dockableState = dockableState; propertySupport.firePropertyChange(PROPERTY_DOCKABLE_STATE, old, dockableState); } public float getResizeWeight(){ return this.resizeWeight; } /** updates the resize weight of this dockable. Valid values range between 0.0f and 1.0f */ public void setResizeWeight(float weight){ this.resizeWeight = weight; } /** Allows any property to be stored in a map associated with this dockkey. A property change event * is propagated to listeners (with a property name equal to "clientProperty." + name) * * * @param name the name used to lookup the property * @param value the value of the property * @since 2.1.2 */ public void putProperty(String name, Object value) { if (clientProperties == null){ clientProperties = new HashMap(); } clientProperties.put(name, value); propertySupport.firePropertyChange("clientProperty."+name, null, value); } /** returns a property associated to this name, or null if the property is undefined * @param name the name used to lookup the property * @since 2.1.2 */ public Object getProperty(String name) { if (clientProperties != null){ return clientProperties.get(name); } else { return null; } } /** returns and removes a property associated to this name, or null if the property is undefined * @param name the name used to lookup the property * @since 2.1.2 */ public Object removeProperty(String name){ if (clientProperties != null){ return clientProperties.remove(name); } else { return null; } } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/DockTabbedPane.java0000644000175000017500000013011210573516346025672 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking; import com.vlsolutions.swing.tabbedpane.JTabbedPaneSmartIcon; import com.vlsolutions.swing.tabbedpane.JTabbedPaneSmartIconManager; import com.vlsolutions.swing.tabbedpane.SmartIconJButton; import java.awt.*; import java.awt.geom.*; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import javax.swing.*; import com.vlsolutions.swing.docking.event.*; import java.awt.event.ActionEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.HashMap; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; /** A JTabbedPane customized for integration with the docking framework. * *

* Defaults : *

* *

* This tabbed pane is not meant to be used outside of DockingDesktop because of * their connected behaviour (drag/drop support, docking constraints, etc). *

* As of version 2.0 of the framework, the tabbed pane displays a close icon (other functions * are available with a right click menu). * * @see DockingDesktop * * @author Lilian Chamontin, vlsolutions. * @version 1.0 * @update 2005/11/01 Lilian Chamontin : enhanced shape painting (tries to avoid * going outside the tab bounds) * @update 2005/11/10 Lilian Chamontin : added support for DnD multiple tabs at once. * @update 2005/12/08 Lilian Chamontin : removed a portion of code as its been refactored in BorderSplitter */ public class DockTabbedPane extends JTabbedPane implements DockDropReceiver, DockableDragSource, TabbedDockableContainer { /* no UI for this component, as it is look and feel dependent : we cannot extend BasicTabbedPaneUI */ /** cache for reusing the general path lastDropPath between calls to getDropShape */ private Rectangle lastDropBounds, lastDropTabBounds; private GeneralPath lastDropPath; /** set by a drag operation */ private SingleDockableContainer draggedDockable = null; /** True when the whole tabbedpane is dragged */ private boolean isMultipleDrag = false; protected DockingDesktop desktop; /** The pop-up menu used to provide fast "close" shortcuts (close all, close others) */ protected JPopupMenu popup = new JPopupMenu(); /** the tab currently associated with the pop-up */ protected int popupTab = -1; /** The tab that was selected before the current one */ protected int previousSelectedDockable = -1; private HashMap closeActions = new HashMap(); // DockKey , Action private JTabbedPaneSmartIconManager tabManager = new JTabbedPaneSmartIconManager(this); /* This pseudo-dockable is used during drag and drop operations of the whole tabbed pane */ static int instanceCount = 0; private Dockable selfDockable= new Dockable(){ DockKey selfKey = new DockKey("dockTab" + instanceCount++); public DockKey getDockKey(){ selfKey.setName(getDockableAt(0).getDockKey().getName() + "..."); return selfKey; } public Component getComponent(){ return DockTabbedPane.this; } }; private PropertyChangeListener keyChangeListener = new PropertyChangeListener(){ public void propertyChange(PropertyChangeEvent e){ DockKey k =(DockKey)e.getSource(); if (e.getPropertyName().equals(DockKey.PROPERTY_CLOSEABLE)){ Action closeAction = (Action)closeActions.get(k); if (closeAction != null){ closeAction.setEnabled(k.isCloseEnabled()); } } else if (e.getPropertyName().equals(DockKey.PROPERTY_ICON)){ int tab = getDockableIndex(k); if (tab >= 0){ JTabbedPaneSmartIcon tabIcon = (JTabbedPaneSmartIcon) getIconAt(tab); tabIcon.setIcon((Icon) e.getNewValue()); JTabbedPaneSmartIcon newIcon = tabIcon.copy(); // we create a copy to trigger a repaint event setIconAt(tab, newIcon); } } else if (e.getPropertyName().equals(DockKey.PROPERTY_NAME)){ int tab = getDockableIndex(k); if (tab >= 0){ JTabbedPaneSmartIcon tabIcon = (JTabbedPaneSmartIcon) getIconAt(tab); String old = tabIcon.getLabel(); String label = (String) e.getNewValue(); tabIcon.setLabel(label); JTabbedPaneSmartIcon newIcon = tabIcon.copy(); // we create a copy to trigger a repaint event setIconAt(tab, newIcon); SwingUtilities.invokeLater(new Runnable(){ public void run(){ // we have to revalidate/repaint to ensure the new icon size is correctly // taken into account revalidate(); repaint(); } }); } } else if (e.getPropertyName().equals(DockKey.PROPERTY_TOOLTIP)){ int tab = getDockableIndex(k); if (tab >= 0){ JTabbedPaneSmartIcon tabIcon = (JTabbedPaneSmartIcon) getIconAt(tab); tabIcon.setTooltipText((String) e.getNewValue()); } } } }; public DockTabbedPane() { int tabPlacement = UIManager.getInt("TabbedDockableContainer.tabPlacement"); setTabLayoutPolicy(WRAP_TAB_LAYOUT); setTabPlacement(tabPlacement); addMouseListener(new MouseAdapter(){ // depending on the platform, pop-up is triggered either by mousePressed or mouseReleased public void mousePressed(MouseEvent e){ if (e.isPopupTrigger()){ // popup only when left button is not pressed checkForPopUp(e); } } public void mouseReleased(MouseEvent e){ if (e.isPopupTrigger()){ checkForPopUp(e); } } public void mouseClicked(MouseEvent e){ if (e.getClickCount() == 2 && SwingUtilities.isLeftMouseButton(e)){ Dockable d = findDockableAt(e); if (d != null && d.getDockKey().isMaximizeEnabled() && d.getDockKey().getDockableState() == DockableState.STATE_DOCKED){ // 2005/10/10 don't maximize floatings desktop.maximize(d); } } } }); if (UIManager.getBoolean("TabbedPane.alternateTabIcons")){ //2005/11/14 // we use a different set of icons addChangeListener(new ChangeListener(){ int prevTab = -1; public void stateChanged(ChangeEvent e){ int selectedTab = getSelectedIndex(); installTabIcons(selectedTab, true); if (prevTab != -1){ installTabIcons(prevTab, false); } previousSelectedDockable = prevTab; prevTab = selectedTab; } }); } } private void installTabIcons(int tab, boolean selected){ if (tab < getTabCount()){ JTabbedPaneSmartIcon icon = (JTabbedPaneSmartIcon) getIconAt(tab); if (icon != null){ SmartIconJButton closeIcon = icon.getSmartButton(0); if (selected){ closeIcon.setIcon(UIManager.getIcon("DockTabbedPane.close")); closeIcon.setPressedIcon(UIManager.getIcon("DockTabbedPane.close.pressed")); closeIcon.setRolloverIcon(UIManager.getIcon("DockTabbedPane.close.rollover")); } else { closeIcon.setIcon(UIManager.getIcon("DockTabbedPane.unselected_close")); closeIcon.setPressedIcon(UIManager.getIcon("DockTabbedPane.unselected_close.pressed")); closeIcon.setRolloverIcon(UIManager.getIcon("DockTabbedPane.unselected_close.rollover")); } icon.setSmartButton(0, closeIcon); } } } /** Returns the tab index of the dockable corresponding to the given key, or null if the dockable * doesn't belong to this tab. */ public int getDockableIndex(DockKey key){ for (int i=0; i < getTabCount(); i++){ Dockable d = getDockableAt(i); if (d != null //2006/12/07 && d.getDockKey().equals(key)){ return i; } } return -1; } private void checkForPopUp(MouseEvent e){ /* Tabbed dockable can be of two states : docked and floating * when floating, the only option is to attach again. */ Dockable d = findDockableAt(e); if (d != null){ DockKey key = d.getDockKey(); // first add the standard menu JPopupMenu popup = new JPopupMenu(key.getName()); int menuCount = 0; if (key.getDockableState() == DockableState.STATE_DOCKED){ if (key.isAutoHideEnabled()){ popup.add(new JMenuItem(TabbedContainerActions.createHideTabAction(d, desktop))); menuCount++; } if (key.isFloatEnabled()){ popup.add(new JMenuItem(TabbedContainerActions.createFloatTabAction(d, desktop))); menuCount++; } if (key.isMaximizeEnabled()){ popup.add(new JMenuItem(TabbedContainerActions.createMaximizeTabAction(d, desktop))); menuCount++; } if (key.isCloseEnabled()){ JMenuItem mItem = new JMenuItem(TabbedContainerActions.createCloseAction(d, desktop)); mItem.setPressedIcon(new ImageIcon(getClass().getResource("close16.gif"))); popup.add(mItem); menuCount++; } } else if (key.getDockableState() == DockableState.STATE_FLOATING){ if (DockingUtilities.isChildOfCompoundDockable(d)){ // as of v2.1 floating dockable which is a child of compound dockable don't have "attach" menu } else { popup.add(new JMenuItem(TabbedContainerActions.createAttachTabAction(d, desktop))); menuCount++; } } else if (key.getDockableState() == DockableState.STATE_HIDDEN){ // a tabbed hidden dockable can only occur when the dockable is child of a compound dockable // in that case, there isn't any general popup option available } else { throw new RuntimeException("invalid state for a tabbed dockable"); } DockableActionCustomizer customizer = d.getDockKey().getActionCustomizer(); if (customizer != null && customizer.isTabSelectorPopUpCustomizer()){ if (menuCount > 0){ popup.addSeparator(); } customizer.visitTabSelectorPopUp(popup, d); } if (menuCount>0){ popup.pack(); popup.show(this, e.getX(), e.getY()); } } } private Dockable findDockableAt(MouseEvent e){ Point p = e.getPoint(); // find the tab on which the mouse has been pressed popupTab = -1; for (int i = 0; i < getTabCount(); i++) { Rectangle tabbounds = getBoundsAt(i); if (tabbounds.contains(p)) { // all right return getDockableAt(i); } } return null; } /** Adds a new tab respecting the presentation and constraints of the component. * * {@inheritDoc} * */ public void addDockable(Dockable dockable, int tab){ SingleDockableContainer dc = DockableContainerFactory.getFactory().createDockableContainer(dockable, DockableContainerFactory.PARENT_TABBED_CONTAINER); dc.installDocking(desktop); addDockableContainer(dc, tab); } private void addDockableContainer(final SingleDockableContainer dc, int tab){ final DockKey key = dc.getDockable().getDockKey(); AbstractAction closeAction = new AbstractAction("Close"){ public void actionPerformed(ActionEvent e){ desktop.close(dc.getDockable()); } }; closeActions.put(key, closeAction); SmartIconJButton closeIcon = new SmartIconJButton(closeAction); if (UIManager.getBoolean("TabbedPane.alternateTabIcons")){ //2005/12/09 closeIcon.setIcon(UIManager.getIcon("DockTabbedPane.unselected_close")); closeIcon.setPressedIcon(UIManager.getIcon("DockTabbedPane.unselected_close.pressed")); closeIcon.setRolloverIcon(UIManager.getIcon("DockTabbedPane.unselected_close.rollover")); } else { closeIcon.setIcon(UIManager.getIcon("DockTabbedPane.close")); closeIcon.setPressedIcon(UIManager.getIcon("DockTabbedPane.close.pressed")); closeIcon.setRolloverIcon(UIManager.getIcon("DockTabbedPane.close.rollover")); } closeAction.setEnabled(key.isCloseEnabled()); // add a tooltip closeAction.putValue(AbstractAction.SHORT_DESCRIPTION, UIManager.get("DockTabbedPane.closeButtonText")); final JTabbedPaneSmartIcon smartIcon = new JTabbedPaneSmartIcon(key.getIcon(), key.getName(), new SmartIconJButton[]{ closeIcon}); smartIcon.setTooltipText(key.getTooltip()); smartIcon.setIconForTabbedPane(this); if (tab >= getTabCount()){ //addTab(key.getName(), key.getIcon(), (Component)dc, key.getTooltip()); addTab("",smartIcon, (Component) dc, key.getTooltip()); //addTab(key.getName(),smartIcon, (Component) dc, key.getTooltip()); tab = getTabCount()-1; } else { //insertTab(key.getName(), key.getIcon(), (Component)dc, key.getTooltip(), tab); insertTab("", smartIcon, (Component)dc, key.getTooltip(), tab); //insertTab(key.getName(), smartIcon, (Component)dc, key.getTooltip(), tab); } key.addPropertyChangeListener(keyChangeListener); revalidate(); repaint(); /* SwingUtilities.invokeLater(new Runnable(){ public void run(){ setTitleAt(getDockableIndex(key), ""); // workaround for painting problems } });*/ } public void processDockableDrag(DockDragEvent e) { scanDrop(e, false); } private void scanDrop(DockEvent event, boolean drop) { // dockDropReceiver DockableDragSource dragSource = event.getDragSource(); // reject operation if the source is an ancestor of this component. if (dragSource.getDockableContainer().isAncestorOf(this)){ // this is possible for compound containers (as they contain sub-dockables) // in that case, you cannnot drop a compound into one of its children // 2007/01/08 if (drop){ ((DockDropEvent) event).rejectDrop(); } else { ((DockDragEvent) event).delegateDrag(); } return; } Dockable dockable = null; SingleDockableContainer dc = null; Container dragContainer = event.getDragSource().getDockableContainer(); if (dragContainer instanceof TabbedDockableContainer){ if (dragContainer == this){ // drop onto itself not possible if (drop){ ((DockDropEvent)event).rejectDrop(); } else { ( (DockDragEvent) event).rejectDrag(); } return; } } else { // fast check to avoid processing a dockable of unknown type dockable = dragSource.getDockable(); dc = DockingUtilities.findSingleDockableContainer(dockable); if (dc == null){ if (drop){ ((DockDropEvent)event).rejectDrop(); } else { ( (DockDragEvent) event).rejectDrag(); } return; } } Point p = event.getMouseEvent().getPoint(); Rectangle vbounds = getSelectedComponent().getBounds(); // is point inside the main tab area ? if (vbounds.contains(p)) { scanMainTabZone(event, drop, dragSource, vbounds); return; } // deny DnD coming from whole tabs if (dragSource.getDockableContainer() instanceof TabbedDockableContainer){ if (drop){ ((DockDropEvent)event).rejectDrop(); } else { ( (DockDragEvent) event).rejectDrag(); } return; } // not in the main zone, check for tabs positions // (but reject first if groups are not compatible) DockableDragSource s = event.getDragSource(); Dockable d = s.getDockable(); DockGroup dragGroup = d.getDockKey().getDockGroup(); for (int i=0; i < getTabCount(); i++){ DockGroup thisGroup = getDockableAt(i).getDockKey().getDockGroup(); if (!DockGroup.areGroupsCompatible( thisGroup, dragGroup)){ if (drop){ ((DockDropEvent) event).rejectDrop(); } else { ((DockDragEvent) event).rejectDrag(); } return; } } for (int i = 0; i < getTabCount(); i++) { Rectangle tabbounds = getBoundsAt(i); if (tabbounds.contains(p)) { // insert before this tab if allowed SingleDockableContainer tab = (SingleDockableContainer)getComponentAt(i); if (tab.getDockable() == dragSource.getDockable()){ if (drop){ ((DockDropEvent)event).rejectDrop(); } else { ((DockDragEvent) event).rejectDrag(); } return; } if (i > 0){ tab = (SingleDockableContainer) getComponentAt(i - 1); if (tab.getDockable() == dragSource.getDockable()) { if (drop){ ((DockDropEvent)event).rejectDrop(); } else { ((DockDragEvent) event).rejectDrag(); } return; } } if (vbounds.equals(lastDropBounds) && tabbounds.equals(lastDropTabBounds)){ // optimized (cached) } else { GeneralPath gp = buildPathForCurrentTab(vbounds, tabbounds); lastDropBounds = vbounds; lastDropTabBounds = tabbounds; lastDropPath = gp; } Dockable draggedDockable = dragSource.getDockable(); int initialState = draggedDockable.getDockKey().getDockableState(); Dockable base = getDockableAt(0); int nextState = base.getDockKey().getDockableState(); event.setDockingAction(new DockingActionCreateTabEvent(event.getDesktop(), draggedDockable, initialState, nextState, base, i)); if (drop){ if (DockingUtilities.findTabbedDockableContainer(dockable) == this){ // the dockable IS another tab of this container, so we just have to // change its tab order. ((DockDropEvent)event).acceptDrop(false); // don't remove addDockableContainer(dc, i); // simply move } else { // request the desktop to create the tab if (base.getDockKey().getDockableState() == DockableState.STATE_FLOATING){ //2005/12/09 if (dragSource.getDockable().getDockKey().getDockableState() == DockableState.STATE_FLOATING){ // this is new 2.1 feature : allowed DnD if the tab is a child of a compund dockable ( (DockDropEvent) event).acceptDrop(); // remove } else { ( (DockDropEvent) event).acceptDrop(false); // don't remove it yet, we need to store its previous dockable state } } else { ( (DockDropEvent) event).acceptDrop(); } desktop.createTab(base, dragSource.getDockable(), i); //2005/10/08 //addDockable(dragSource.getDockable(), i); //2005/10/08 } setSelectedIndex(i); } else { ((DockDragEvent) event).acceptDrag(lastDropPath); } return; } } // not on the tabs, check if after the last int lastTab = getTabCount() -1; Rectangle lasttabbounds = getBoundsAt(lastTab); Rectangle afterlast = new Rectangle(lasttabbounds.x + lasttabbounds.width, lasttabbounds.y, getX() + getWidth() - (lasttabbounds.x+ lasttabbounds.width), lasttabbounds.height); if (afterlast.contains(p)){ SingleDockableContainer dockableContainer = (SingleDockableContainer)getComponentAt(lastTab); if (dockableContainer.getDockable() == dragSource.getDockable()){ if (drop){ ((DockDropEvent)event).rejectDrop(); } else { ((DockDragEvent) event).rejectDrag(); } return; } if (vbounds.equals(lastDropBounds) && afterlast.equals(lastDropTabBounds)){ } else { GeneralPath gp = buildPathAfterLastTab(vbounds, afterlast); lastDropBounds = vbounds; lastDropTabBounds = afterlast; lastDropPath = gp; } Dockable draggedDockable = dragSource.getDockable(); int initialState = draggedDockable.getDockKey().getDockableState(); Dockable base = getDockableAt(0); int nextState = base.getDockKey().getDockableState(); event.setDockingAction(new DockingActionCreateTabEvent(event.getDesktop(), draggedDockable, initialState, nextState, base, lastTab+1)); if (drop){ if (DockingUtilities.findTabbedDockableContainer(dockable) == this){ // the dockable IS another tab of this container, so we just have to // change its tab order. ((DockDropEvent)event).acceptDrop(false); // don't remove addDockableContainer(dc, lastTab+1); // simply move } else { if (base.getDockKey().getDockableState() == DockableState.STATE_FLOATING){ //2005/12/09 if (dragSource.getDockable().getDockKey().getDockableState() == DockableState.STATE_FLOATING){ // this is new 2.1 feature : allowed DnD if the tab is a child of a compund dockable ( (DockDropEvent) event).acceptDrop(); // remove } else { ( (DockDropEvent) event).acceptDrop(false); // don't remove it yet, we need to store its previous dockable state } } else { ( (DockDropEvent) event).acceptDrop(); } desktop.createTab(base, dragSource.getDockable(), lastTab+1); //2005/10/08 //addDockable(dragSource.getDockable(), lastTab+1); } setSelectedIndex(getTabCount()-1); } else { ((DockDragEvent) event).acceptDrag(lastDropPath); } return; } lastDropBounds = null; lastDropTabBounds = null; lastDropPath = null; if (drop){ ((DockDropEvent)event).rejectDrop(); } else { ((DockDragEvent) event).rejectDrag(); } } /** Creates a general path suitable for showing tab insertion before the currentTab*/ protected GeneralPath buildPathForCurrentTab(Rectangle vbounds, Rectangle tabbounds){ GeneralPath gp = new GeneralPath(); if (getTabPlacement() == SwingConstants.BOTTOM){ gp.moveTo(vbounds.x, vbounds.y); gp.lineTo(vbounds.x + vbounds.width, vbounds.y); gp.lineTo(vbounds.x + vbounds.width, vbounds.y + vbounds.height); int height = Math.min(16, tabbounds.height); if (getTabRunCount() > 1 && (tabbounds.y > vbounds.y + vbounds.height + 10) ){ gp.lineTo(vbounds.x , vbounds.y + vbounds.height); gp.closePath(); gp.moveTo(tabbounds.x, tabbounds.y); gp.lineTo(tabbounds.x + 30, tabbounds.y); gp.lineTo(tabbounds.x + 25, tabbounds.y + height); gp.lineTo(tabbounds.x, tabbounds.y + height); gp.closePath(); } else { gp.lineTo(tabbounds.x + 30, vbounds.y + vbounds.height); gp.lineTo(tabbounds.x + 25, vbounds.y + vbounds.height + height); gp.lineTo(tabbounds.x, vbounds.y + vbounds.height + height); gp.lineTo(tabbounds.x, vbounds.y + vbounds.height); gp.lineTo(vbounds.x, vbounds.y + vbounds.height); gp.closePath(); } } else { // TOP int height = Math.min(16, tabbounds.height); gp.moveTo(vbounds.x, vbounds.y); if (getTabRunCount() > 1 && (tabbounds.y + tabbounds.height < vbounds.y - 10) ){ gp.lineTo(vbounds.x + vbounds.width, vbounds.y); gp.lineTo(vbounds.x + vbounds.width, vbounds.y + vbounds.height); gp.lineTo(vbounds.x , vbounds.y + vbounds.height); gp.closePath(); gp.moveTo(tabbounds.x, tabbounds.y); gp.lineTo(tabbounds.x + 25, tabbounds.y); gp.lineTo(tabbounds.x + 30, tabbounds.y + height); gp.lineTo(tabbounds.x, tabbounds.y + height); gp.closePath(); } else { gp.lineTo(tabbounds.x, vbounds.y); gp.lineTo(tabbounds.x, vbounds.y - height); gp.lineTo(tabbounds.x + 25, vbounds.y - height); gp.lineTo(tabbounds.x + 30, vbounds.y); gp.lineTo(vbounds.x + vbounds.width, vbounds.y); gp.lineTo(vbounds.x + vbounds.width, vbounds.y + vbounds.height); gp.lineTo(vbounds.x, vbounds.y + vbounds.height); gp.closePath(); } } return gp; } /** Creates a general path suitable for showing tab insertion after the last tab*/ protected GeneralPath buildPathAfterLastTab(Rectangle vbounds, Rectangle afterlast){ GeneralPath gp = new GeneralPath(); if (getTabPlacement() == SwingConstants.BOTTOM){ int height = Math.min(16, afterlast.height); gp.moveTo(vbounds.x, vbounds.y); gp.lineTo(vbounds.x + vbounds.width, vbounds.y); gp.lineTo(vbounds.x + vbounds.width, vbounds.y + vbounds.height); if (getTabRunCount() > 1){ gp.lineTo(vbounds.x , vbounds.y + vbounds.height); gp.closePath(); gp.moveTo(afterlast.x, afterlast.y); gp.lineTo(afterlast.x + 30, afterlast.y); gp.lineTo(afterlast.x + 25, afterlast.y + height); gp.lineTo(afterlast.x, afterlast.y + height); gp.closePath(); } else { if (afterlast.x + 30 > vbounds.x +vbounds.width){ // we're outside the component bounds, so we go back a little bit int newX = vbounds.x + vbounds.width - 30; gp.lineTo(newX + 30, vbounds.y + vbounds.height); gp.lineTo(newX + 25, vbounds.y + vbounds.height + height); gp.lineTo(newX, vbounds.y + vbounds.height + height); gp.lineTo(newX, vbounds.y + vbounds.height); } else { gp.lineTo(afterlast.x + 30, vbounds.y + vbounds.height); gp.lineTo(afterlast.x + 25, vbounds.y + vbounds.height + height); gp.lineTo(afterlast.x, vbounds.y + vbounds.height + height); gp.lineTo(afterlast.x, vbounds.y + vbounds.height); } gp.lineTo(vbounds.x, vbounds.y + vbounds.height); gp.closePath(); } } else { // TOP int height = Math.min(16, afterlast.height); gp.moveTo(vbounds.x, vbounds.y); if (getTabRunCount() > 1){ gp.lineTo(vbounds.x + vbounds.width, vbounds.y); gp.lineTo(vbounds.x + vbounds.width, vbounds.y + vbounds.height); gp.lineTo(vbounds.x , vbounds.y + vbounds.height); gp.closePath(); gp.moveTo(afterlast.x, afterlast.y); gp.lineTo(afterlast.x + 25, afterlast.y); gp.lineTo(afterlast.x + 30, afterlast.y + height); gp.lineTo(afterlast.x, afterlast.y + height); gp.closePath(); } else { if (afterlast.x + 30 > vbounds.x +vbounds.width){//2005/11/01 // we're outside the component bounds, so we go back a little bit int newX = vbounds.x + vbounds.width - 30; gp.lineTo(newX, vbounds.y); gp.lineTo(newX, vbounds.y - height); gp.lineTo(newX + 25, vbounds.y - height); gp.lineTo(newX + 30, vbounds.y); } else { gp.lineTo(afterlast.x, vbounds.y); gp.lineTo(afterlast.x, vbounds.y - height); gp.lineTo(afterlast.x + 25, vbounds.y - height); gp.lineTo(afterlast.x + 30, vbounds.y); } gp.lineTo(vbounds.x + vbounds.width, vbounds.y); gp.lineTo(vbounds.x + vbounds.width, vbounds.y + vbounds.height); gp.lineTo(vbounds.x, vbounds.y + vbounds.height); gp.closePath(); } } return gp; } private void scanMainTabZone(DockEvent event, boolean drop, DockableDragSource dragSource, Rectangle vbounds) { Point p = event.getMouseEvent().getPoint(); /* allow drop : * - on the current tab * - between tabs * delegate drop if mouse to near of the borders */ if (scanBorderBounds(event, drop, p)) { return; } // deny DnD coming from whole tabs if (dragSource.getDockableContainer() instanceof TabbedDockableContainer){ if (drop){ ((DockDropEvent)event).rejectDrop(); } else { ( (DockDragEvent) event).rejectDrag(); } return; } if (scanSameComponent(event, drop, dragSource)){ return; } if (scanAdjacentTab(event, drop, dragSource)) { return ; } // reject if all key groups aren't compatible DockGroup dragGroup = event.getDragSource().getDockable().getDockKey().getDockGroup(); for (int i=0; i < getTabCount(); i++){ DockGroup thisGroup = getDockableAt(i).getDockKey().getDockGroup(); if (!DockGroup.areGroupsCompatible( thisGroup, dragGroup)){ if (drop){ ((DockDropEvent) event).rejectDrop(); } else { ((DockDragEvent) event).rejectDrag(); } return; } } // now we know we can insert the dragged component here int tab = getSelectedIndex(); Rectangle tabbounds = getBoundsAt(tab); if (vbounds.equals(lastDropBounds) && tabbounds.equals(lastDropTabBounds)) { // optimized (cached) } else { // insert before tab GeneralPath gp = buildPathForCurrentTab(vbounds, tabbounds); lastDropBounds = vbounds; lastDropTabBounds = tabbounds; lastDropPath = gp; } Dockable base = getDockableAt(0); Dockable draggedDockable = dragSource.getDockable(); int initialState = draggedDockable.getDockKey().getDockableState(); int nextState = base.getDockKey().getDockableState(); if (drop) { event.setDockingAction(new DockingActionCreateTabEvent(event.getDesktop(), draggedDockable, initialState, nextState, base, tab )); if (base.getDockKey().getDockableState() == DockableState.STATE_FLOATING){//2005/12/09 if (dragSource.getDockable().getDockKey().getDockableState() == DockableState.STATE_FLOATING){ // this is new 2.1 feature : allowed DnD if the tab is a child of a compound dockable ( (DockDropEvent) event).acceptDrop(); // remove } else { ( (DockDropEvent) event).acceptDrop(false); // don't remove it yet, we need to store its previous dockable state } } else { ( (DockDropEvent) event).acceptDrop(); } //addDockable(event.getDragSource().getDockable(), tab); //event.getDesktop().addToTabbedGroup(base, event.getDragSource().getDockable()); //2005/07/13 desktop.createTab(base, dragSource.getDockable(), tab); //2005/10/08 setSelectedIndex(tab); // dockingPanel.moveDock(dragSource.getTargetKey(), dc); } else { event.setDockingAction(new DockingActionCreateTabEvent(event.getDesktop(), draggedDockable, initialState, nextState, base, tab )); ( (DockDragEvent) event).acceptDrag(lastDropPath); } return; } private boolean scanAdjacentTab(DockEvent event, boolean drop, DockableDragSource dragSource) { if (getSelectedIndex() > 0){ // check and reject a drag/drop of [tab-1] on [tab] SingleDockableContainer dockableContainer = (SingleDockableContainer)getComponentAt(getSelectedIndex()-1); if (dockableContainer.getDockable() == dragSource.getDockable()){ if (drop){ ((DockDropEvent)event).rejectDrop(); } else { ((DockDragEvent) event).rejectDrag(); } return true; } } return false; } private boolean scanSameComponent(DockEvent event, boolean drop, DockableDragSource dragSource) { SingleDockableContainer dockableContainer = (SingleDockableContainer)getSelectedComponent(); if (dockableContainer.getDockable() == dragSource.getDockable()){ // cannot drag/drop onto itself if (drop) { ( (DockDropEvent) event).rejectDrop(); } else { ( (DockDragEvent) event).rejectDrag(); } return true; } return false; } private boolean scanBorderBounds(DockEvent event, boolean drop, Point p) { /** we early reject this operation if the tab is used by a floating dialog */ Dockable firstDockable = getDockableAt(0); if (firstDockable.getDockKey().getDockableState() == DockableState.STATE_FLOATING){ // as of v2.1 this DnD operation is allowed if the tabbed pane is a child of a compund dockable if (!DockingUtilities.isChildOfCompoundDockable(firstDockable)){ // not a nested child return false; } } Rectangle innerBounds = null; if (getTabPlacement() == SwingConstants.BOTTOM){ int yTab = getBoundsAt(0).y; // upper coordinate of tabbed selectors innerBounds = new Rectangle(20, 20, getWidth()-20-20, yTab-20-20); /** @todo : clamp values */ } else { // TOP Rectangle tabBounds = getBoundsAt(0); int yTab = tabBounds.y + tabBounds.height; // lower coordinate of tabbed selectors innerBounds = new Rectangle(20, yTab+20, getWidth()-20-20, getHeight() - yTab-20-20); } if (! innerBounds.contains(p)){ // too near of the bounds, suggest a split docking BorderSplitter splitter = new BorderSplitter(this) /* NO LONGER NEEDED : REIMPLEMENTED IN BORDER SPLITTER 2005/12/08 { // we override split in order to resolve the case where // the drop operation would remove this tabpane from the containment // hierarchy public void split(DockDropEvent event, Container draggedContainer, DockingConstants.Split position){ if (getTabCount() == 1){ // there is only one tab left, meaning // this tabbedpane has already been removed from containment hierarchy Dockable remainingDockable = getDockableAt(0); event.getDesktop().split( remainingDockable, // one of the remaining dockables event.getDragSource().getDockable(), position); } else { super.split(event, draggedContainer, position); // standard behaviour } } }*/; if (drop){ splitter.processDockableDrop((DockDropEvent) event); } else { splitter.processDockableDrag((DockDragEvent) event); } return true; } return false; } /** {@inheritDoc} */ public void processDockableDrop(DockDropEvent event) { scanDrop(event, true); } /** {@inheritDoc} */ public boolean startDragComponent(Point p) { clearDragState(); // which component is dragged ? for (int i = 0; i < getTabCount(); i++) { Rectangle tabbounds = getBoundsAt(i); if (tabbounds.contains(p)) { draggedDockable = (SingleDockableContainer) getComponentAt(i); if (i > 2 && i == getTabCount()-1){ // workaround for a focus problem : when the JTabbedPane has focus on the last tab // and we start a drag (and drop outside the tabbedpane, there is a // nonblocking stacktrace due to a bad focusIndex in BasicTabbedPaneUI (method focusLost() of the Handler) KeyboardFocusManager.getCurrentKeyboardFocusManager().upFocusCycle(); // by putting the focus up before the drop occurs, we ensure a good focusIndex is set } return true; } } // search for whole tab drag : look after last tab and in-between tabs Rectangle header = getBoundsAt(0); header.x = 0; int lastTab = getTabCount() -1; Rectangle lasttabbounds = getBoundsAt(lastTab); header = header.union(lasttabbounds); Rectangle afterlast = new Rectangle(lasttabbounds.x + lasttabbounds.width, lasttabbounds.y, getX() + getWidth() - (lasttabbounds.x+ lasttabbounds.width), lasttabbounds.height); if (afterlast.contains(p) || header.contains(p)){ // either after the last tab or between tabs this.isMultipleDrag = true; return true; } return false; } /** {@inheritDoc} */ public Dockable getDockable() { // from DockableDragSource if (isMultipleDrag){ return selfDockable; } else { if (draggedDockable != null){ return draggedDockable.getDockable(); } return null; } } /** {@inheritDoc} */ public Dockable getSelectedDockable() { Component comp = getComponentAt(getSelectedIndex()); if (comp instanceof SingleDockableContainer){ return ((SingleDockableContainer)comp).getDockable() ; } else { // this may happen when the dockable is maximized : it is temporarily replaced by an // impostor (a JLabel) return null; } } /** {@inheritDoc} */ public void setSelectedDockable(Dockable dockable) { Component c = (Component)DockingUtilities.findSingleDockableContainer(dockable); if (c != null && indexOfComponent(c) >= 0){ setSelectedComponent(c); } } /** {@inheritDoc} */ public Dockable getDockableAt(int index) { Component c = getComponentAt(index); if (c instanceof SingleDockableContainer){ return ((SingleDockableContainer)c).getDockable() ; } else { return null; } } /** {@inheritDoc} */ public void removeDockable(Dockable dockable) { DockableContainer dc = DockingUtilities.findSingleDockableContainer(dockable); if (dc != null){ // after a dockable is removed, we go back to the previously selected if still visible if (previousSelectedDockable != -1 && previousSelectedDockable < getTabCount()){ final Dockable d = getDockableAt(previousSelectedDockable); SwingUtilities.invokeLater(new Runnable(){ public void run(){ setSelectedDockable(d); } }); } remove( (Component) dc); // clean up key / actions references / listeners closeActions.remove(dockable.getDockKey()); dockable.getDockKey().removePropertyChangeListener(keyChangeListener); } } /** {@inheritDoc} */ public void removeDockable(int index) { Dockable dockable = getDockableAt(index); final int prev = this.previousSelectedDockable; SwingUtilities.invokeLater(new Runnable(){ public void run(){ if (prev != -1 && prev < getTabCount()){ setSelectedIndex(prev); } } }); removeTabAt(index); // clean up key / actions references / listeners closeActions.remove(dockable.getDockKey()); dockable.getDockKey().removePropertyChangeListener(keyChangeListener); } private void clearDragState(){ // reset drag variables this.draggedDockable = null; this.isMultipleDrag = false; } /** {@inheritDoc} */ public String toString(){ return "DockTabbedPane [" + Integer.toHexString(hashCode()) + " - tabcount=" + getTabCount() + "]"; } /** {@inheritDoc} */ public int indexOfDockable(Dockable dockable) { DockableContainer dc = DockingUtilities.findSingleDockableContainer(dockable); if (dc != null){ return indexOfComponent((Component)dc); } else { return -1; } } /** {@inheritDoc} */ public void installDocking(DockingDesktop desktop) { this.desktop = desktop; desktop.installDockableDragSource(this); } /** {@inheritDoc} */ public void uninstallDocking(DockingDesktop desktop) { desktop.uninstallDockableDragSource(this); } public Container getDockableContainer() { if (isMultipleDrag){ return this; } else { return ((Container)draggedDockable); } } public void endDragComponent(boolean dropped) { // nothing more to do } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/DockView.java0000644000175000017500000004015110573516346024622 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking; import java.beans.*; import java.awt.*; import java.awt.geom.*; import javax.swing.*; import javax.swing.event.*; import com.vlsolutions.swing.docking.event.*; /** DefaultImplementation of the SingleDockableContainer. *

* A Dockview is the component responsible for displaying a single user * component inside a DockingPanel. *

* The DockView contains a DockViewTitleBar, used as a header to display useful information * and optional controls (close/maximize/hide/float) *

* UI : The user component is displayed with decorations provided by a * {@link com.vlsolutions.swing.docking.ui.DockViewUI} delegate. *

* Here is an example (VLDocking 1.1 "shadow" style) : *

*

Sample DockView

* *

* Note : multiple user-components are not displayable by the dockview : * the default implementation of TabbedDockableContainer is the {@link DockTabbedPane}. * * @see DockViewTitleBar * * @author Lilian Chamontin, vlsolutions. * @version 1.0 * @update 2005/12/09 Lilian Chamontin : added NPE safety check around uninstallDocking as sometimes * uninstalling is done twice. * @update 2007/01/08 Lilian Chamontin : delegated the creation of the titlebar to allow easy override. */ public class DockView extends JPanel implements DockDropReceiver, SingleDockableContainer { private static final String uiClassID = "DockViewUI"; protected DockViewTitleBar title = getTitleBar(); /** the desktop managing this view */ protected DockingDesktop desktop; /** the dockable managed by this view */ protected Dockable dockable; //user component /** remember the last drop position to cache the shape used for showing the drop position */ protected Shape lastDropShape, lastDropGeneralPath; /** listen to the titlebar actions */ private PropertyChangeListener listener = new PropertyChangeListener(){ public void propertyChange(PropertyChangeEvent e) { if (e.getPropertyName().equals(DockViewTitleBar.PROPERTY_AUTOHIDE)){ if (e.getOldValue().equals(Boolean.TRUE)){ // from autohide to dock : not possible because DockView isn't used } else { // dock to autohide desktop.setAutoHide(dockable, true); } } else if (e.getPropertyName().equals(DockViewTitleBar.PROPERTY_CLOSED)){ desktop.close(dockable); } else if (e.getPropertyName().equals(DockViewTitleBar.PROPERTY_MAXIMIZED)){ if (e.getNewValue().equals(Boolean.TRUE)){ desktop.maximize(dockable); } else { desktop.restore(dockable); } } else if (e.getPropertyName().equals(DockViewTitleBar.PROPERTY_FLOAT)){ desktop.setFloating(dockable, ((Boolean)e.getNewValue()).booleanValue()); } } }; /** Constructs an empty DockView. *

* A {@link #setDockable(Dockable)} call is requiered for this constructor to be usefull. * */ public DockView() { super(new BorderLayout()); add(title, BorderLayout.NORTH); } /** Constructs a new DockView for the given dockable. * * @param dockable the dockable to show * */ public DockView(Dockable dockable){ this(); setDockable(dockable); } /** Constructs a new DockView for the given dockable. * * @param dockable the dockable to show * */ public DockView(Dockable dockable, boolean showTitle){ super(new BorderLayout()); add(title, BorderLayout.NORTH); if (!showTitle){ title.setVisible(false); } setDockable(dockable); } /** Returns the contained component * * {@inheritDoc} * */ public Dockable getDockable(){ return dockable; } /** Adds the dockable's component to this DockView. * * * @param dockable the user dockable */ public void setDockable(Dockable dockable){ this.dockable = dockable; add(dockable.getComponent(), BorderLayout.CENTER); if (title != null){ title.setDockable(dockable); } // allow resizing of split pane beyond minimum size // could be replaced by adding a JScrollPane instead of panels setMinimumSize(new Dimension(30,30)); } /** {@inheritDoc} */ public String toString(){ return "DockView of " + dockable.getDockKey(); } /** {@inheritDoc} * @since 2.0 */ public String getUIClassID() { return uiClassID; } /** {@inheritDoc}. */ public void processDockableDrag(DockDragEvent event) { scanDrop(event, false); } /** {@inheritDoc} *

* Please note that a drag into a DockView can also lead to create a DockTabbedPane. */ public void processDockableDrop(DockDropEvent event) { scanDrop(event, true); } /* common method for drag && drop gesture support */ protected void scanDrop(DockEvent event, boolean drop){ // reject operation if the source is an ancestor of this view. if (event.getDragSource().getDockableContainer().isAncestorOf(this)){ // this is possible for compound containers (as they contain sub-dockables) // in that case, you cannnot drop a compound into one of its children // 2007/01/08 if (drop){ ((DockDropEvent) event).rejectDrop(); } else { ((DockDragEvent) event).delegateDrag(); } return; } if (getParent() instanceof TabbedDockableContainer){ // cannot nest DockTabbedPanes if (drop){ ((DockDropEvent) event).rejectDrop(); } else { ((DockDragEvent) event).delegateDrag(); } return; } if (event.getDragSource().getDockable() == dockable) { // cannot drop onto itself if (drop){ ((DockDropEvent) event).rejectDrop(); } else { ((DockDragEvent) event).rejectDrag(); } return; } // The dockview isn't contained inside a tabbedpane, so there are now 5 drop zones : // - center : create a tabbedpane // - top/left/bottom/right : split the view Rectangle bounds = getBounds(); BorderSplitter splitter = new BorderSplitter(this); boolean accepted; if (drop){ splitter.processDockableDrop((DockDropEvent)event); accepted = ((DockDropEvent)event).isDropAccepted(); } else { splitter.processDockableDrag((DockDragEvent)event); accepted = ((DockDragEvent)event).isDragAccepted(); } if (! accepted){ // not on the borders : we should create a new tab if (event.getDragSource().getDockableContainer() instanceof TabbedDockableContainer) { // cannot drop a whole tab container if (drop){ ((DockDropEvent) event).rejectDrop(); } else { ((DockDragEvent) event).rejectDrag(); } return; } // reject if key groups aren't compatible DockGroup thisGroup = dockable.getDockKey().getDockGroup(); DockGroup dragGroup = event.getDragSource().getDockable().getDockKey().getDockGroup(); if (!DockGroup.areGroupsCompatible( thisGroup, dragGroup)){ if (drop){ ((DockDropEvent) event).rejectDrop(); } else { ((DockDragEvent) event).rejectDrag(); } return; } Dockable d = event.getDragSource().getDockable(); int dockableState = d.getDockKey().getDockableState(); int viewState = dockable.getDockKey().getDockableState(); if (drop){ event.setDockingAction(new DockingActionCreateTabEvent(event.getDesktop(), d, dockableState, viewState, dockable, 0)); /*if (dockable.getDockKey().getDockableState() == DockableState.STATE_FLOATING){ ((DockDropEvent) event).acceptDrop(false); // don't remove a floating dockable from its hierarchy yet } else {*/ ((DockDropEvent) event).acceptDrop(); /*} */ desktop.createTab(dockable, event.getDragSource().getDockable(), 0, true); } else { event.setDockingAction(new DockingActionCreateTabEvent(event.getDesktop(), d, dockableState, viewState, dockable, 0)); Rectangle2D r2d = new Rectangle2D.Float(bounds.x, bounds.y, bounds.width, bounds.height); if (r2d.equals(lastDropShape)) { // optimized shape caching ( (DockDragEvent) event).acceptDrag(lastDropGeneralPath); } else { // draw a 'tabbed pane shape' GeneralPath path = buildPathForTab(bounds);; lastDropShape = r2d; lastDropGeneralPath = path; ( (DockDragEvent) event).acceptDrag(lastDropGeneralPath); } } } } /** Create a path used to display the drag shape of a tab container */ protected GeneralPath buildPathForTab(Rectangle bounds){ GeneralPath path = new GeneralPath(); int tabPlacement = UIManager.getInt("TabbedDockableContainer.tabPlacement"); if (tabPlacement == SwingConstants.BOTTOM){ Rectangle tabRect = new Rectangle(0, 0, bounds.width - 5, bounds.height - 5); path.moveTo(tabRect.x, tabRect.y); path.lineTo(tabRect.x + tabRect.width, tabRect.y); path.lineTo(tabRect.x + tabRect.width, tabRect.y + tabRect.height - 15); path.lineTo(tabRect.x + 30, tabRect.y + tabRect.height - 15); path.lineTo(tabRect.x + 25, tabRect.y + tabRect.height); path.lineTo(tabRect.x + 10, tabRect.y + tabRect.height); path.lineTo(tabRect.x + 10, tabRect.y + tabRect.height - 15); path.lineTo(tabRect.x, tabRect.y + tabRect.height - 15); path.closePath(); } else { // TOP Rectangle tabRect = new Rectangle(0, 20, bounds.width - 5, bounds.height - 20-5); path.moveTo(tabRect.x, tabRect.y); path.lineTo(tabRect.x + 10, tabRect.y); path.lineTo(tabRect.x + 10, tabRect.y - 15); path.lineTo(tabRect.x + 25, tabRect.y - 15); path.lineTo(tabRect.x + 30, tabRect.y ); path.lineTo(tabRect.x + tabRect.width, tabRect.y); path.lineTo(tabRect.x + tabRect.width, tabRect.y + tabRect.height); path.lineTo(tabRect.x, tabRect.y + tabRect.height); path.closePath(); } return path; } /** {@inheritDoc} */ public void installDocking(DockingDesktop desktop) { this.desktop = desktop; desktop.installDockableDragSource(title); title.addPropertyChangeListener(DockViewTitleBar.PROPERTY_AUTOHIDE, listener); title.addPropertyChangeListener(DockViewTitleBar.PROPERTY_CLOSED, listener); title.addPropertyChangeListener(DockViewTitleBar.PROPERTY_MAXIMIZED, listener); title.addPropertyChangeListener(DockViewTitleBar.PROPERTY_FLOAT, listener); title.installDocking(desktop); } /** {@inheritDoc} */ public void uninstallDocking(DockingDesktop desktop) { if (title != null){ // safety check, as removing is sometimes cascaded and done once more than it should be 2005/12/09 desktop.uninstallDockableDragSource(title); title.removePropertyChangeListener(DockViewTitleBar.PROPERTY_AUTOHIDE, listener); title.removePropertyChangeListener(DockViewTitleBar.PROPERTY_CLOSED, listener); title.removePropertyChangeListener(DockViewTitleBar.PROPERTY_MAXIMIZED, listener); title.removePropertyChangeListener(DockViewTitleBar.PROPERTY_FLOAT, listener); title.uninstallDocking(desktop); } //remove(title); title = null; this.desktop = null; } /** Returns (or creates) the title bar of this dockview */ public DockViewTitleBar getTitleBar(){ if (title == null){ title = DockableContainerFactory.getFactory().createTitleBar();//2007/01/08 } return title; } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/DockViewAsTab.java0000644000175000017500000004126010573516344025535 0ustar twernertwernerpackage com.vlsolutions.swing.docking; import com.vlsolutions.swing.tabbedpane.JTabbedPaneSmartIcon; import com.vlsolutions.swing.tabbedpane.JTabbedPaneSmartIconManager; import com.vlsolutions.swing.tabbedpane.SmartIconJButton; import java.awt.BorderLayout; import java.awt.Container; import java.awt.Dimension; import java.awt.Point; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.ArrayList; import javax.swing.AbstractAction; import javax.swing.Icon; import javax.swing.JMenuItem; import javax.swing.JPopupMenu; import javax.swing.JTabbedPane; import javax.swing.KeyStroke; import javax.swing.UIManager; /** This component is used to display single dockables like if they were in a tabbed pane. *

* Please note this component is still in its early stages and might change in future releases. *

* To use it, just install the TabFactory as DockableContainerFactory * * @author Lilian Chamontin, VLSolutions * @see TabFactory * @since 2.1.3 */ public class DockViewAsTab extends DockView implements SingleDockableContainer { private static final String CLOSE_TEXT = UIManager.getString("DockViewTitleBar.closeButtonText"); private static final String ICONIFY_TEXT = UIManager.getString("DockViewTitleBar.minimizeButtonText"); private static final String RESTORE_TEXT = UIManager.getString("DockViewTitleBar.restoreButtonText"); private static final String MAXIMIZE_TEXT = UIManager.getString("DockViewTitleBar.maximizeButtonText"); private static final String FLOAT_TEXT = UIManager.getString("DockViewTitleBar.floatButtonText"); private static final String ATTACH_TEXT = UIManager.getString("DockViewTitleBar.attachButtonText"); private static Icon closeIcon = UIManager.getIcon("DockViewTitleBar.menu.close"); private static Icon maximizeIcon = UIManager.getIcon("DockViewTitleBar.menu.maximize"); private static Icon restoreIcon = UIManager.getIcon("DockViewTitleBar.menu.restore"); private static Icon hideIcon = UIManager.getIcon("DockViewTitleBar.menu.hide"); private static Icon dockIcon = UIManager.getIcon("DockViewTitleBar.menu.dock"); private static Icon floatIcon = UIManager.getIcon("DockViewTitleBar.menu.float"); private static Icon attachIcon = UIManager.getIcon("DockViewTitleBar.menu.attach"); /** The tab container in which the components are added */ protected TabHeader tabHeader = createTabHeader(); /** smart icon manager */ protected JTabbedPaneSmartIconManager tpManager = new JTabbedPaneSmartIconManager(tabHeader); /** smart icon used to display the title */ protected JTabbedPaneSmartIcon smartIcon = new JTabbedPaneSmartIcon(null, " ", null); protected AbstractAction closeAction = new AbstractAction("Close"){ public void actionPerformed(ActionEvent e){ desktop.close(getDockable()); } }; protected SmartIconJButton closeSmartIcon = new SmartIconJButton(closeAction); protected AbstractAction maximizeAction = new AbstractAction("Maximize"){ public void actionPerformed(ActionEvent e){ maximizeAction(); } }; protected SmartIconJButton maximizeSmartIcon = new SmartIconJButton(maximizeAction); protected AbstractAction hideAction = new AbstractAction("Hide"){ public void actionPerformed(ActionEvent e){ desktop.setAutoHide(getDockable(), true); } }; protected SmartIconJButton hideSmartIcon = new SmartIconJButton(hideAction); protected AbstractAction floatAction = new AbstractAction("Float"){ public void actionPerformed(ActionEvent e){ desktop.setFloating(getDockable(), true); } }; protected SmartIconJButton floatSmartIcon = new SmartIconJButton(floatAction); // flags to hide/show buttons in the title bar (they are always visible in the contextual menu, but might // take too much space on the titles (for example a minimum set could be hide/float/close // as maximize is accessed by double click) protected boolean isCloseButtonDisplayed = UIManager.getBoolean("DockViewTitleBar.isCloseButtonDisplayed"); protected boolean isHideButtonDisplayed = UIManager.getBoolean("DockViewTitleBar.isHideButtonDisplayed"); protected boolean isDockButtonDisplayed = UIManager.getBoolean("DockViewTitleBar.isDockButtonDisplayed"); protected boolean isMaximizeButtonDisplayed= UIManager.getBoolean("DockViewTitleBar.isMaximizeButtonDisplayed"); protected boolean isRestoreButtonDisplayed= UIManager.getBoolean("DockViewTitleBar.isRestoreButtonDisplayed"); protected boolean isFloatButtonDisplayed= UIManager.getBoolean("DockViewTitleBar.isFloatButtonDisplayed"); protected boolean isAttachButtonDisplayed= UIManager.getBoolean("DockViewTitleBar.isAttachButtonDisplayed"); /** listen to the key changes */ private PropertyChangeListener keyListener = new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent e) { String pName = e.getPropertyName(); if (pName.equals(DockKey.PROPERTY_ICON)) { smartIcon.setIcon( (Icon) e.getNewValue()); } else if (pName.equals(DockKey.PROPERTY_NAME)) { smartIcon.setLabel( (String) e.getNewValue()); revalidate(); } else if (pName.equals(DockKey.PROPERTY_TOOLTIP)) { smartIcon.setTooltipText( (String) e.getNewValue()); } else if (pName.equals(DockKey.PROPERTY_AUTOHIDEABLE)){ resetTabIcons(); } else if (pName.equals(DockKey.PROPERTY_CLOSEABLE)){ resetTabIcons(); } else if (pName.equals(DockKey.PROPERTY_FLOATABLE)){ resetTabIcons(); } else if (pName.equals(DockKey.PROPERTY_MAXIMIZABLE)){ resetTabIcons(); } } }; private JPopupMenu currentPopUp = null; /** reacts to single and double click on title bar */ private MouseListener titleMouseListener = new MouseAdapter() { public void mouseClicked(MouseEvent e) { if (e.getClickCount() == 2) { maximizeAction(); } else { getDockable().getComponent().requestFocus(); } } public void mousePressed(MouseEvent e){ if (e.isPopupTrigger()){ checkForPopUp(e); } } public void mouseReleased(MouseEvent e){ if (e.isPopupTrigger()){ checkForPopUp(e); } } }; private ActionListener actionListener = new ActionListener(){ public void actionPerformed(ActionEvent e){ if (e.getActionCommand().equals("dock")){ dockAction(); } else if (e.getActionCommand().equals("close")){ closeAction(); } else if (e.getActionCommand().equals("maximize")){ maximizeAction(); } else if (e.getActionCommand().equals("float")){ floatAction(); } } }; public DockViewAsTab(Dockable dockable){ super(dockable, false); add(tabHeader, BorderLayout.CENTER); tabHeader.addMouseListener(titleMouseListener); configureCloseButton(); configureHideButton(); configureMaximizeButton(); configureFloatButton(); setDockableAsTab(dockable); } private void checkForPopUp(MouseEvent e){ Dockable target = getDockable(); JPopupMenu popup = new JPopupMenu(target.getDockKey().getName()); // first add the standard menu DockKey key = target.getDockKey(); switch (key.getDockableState()){ case DockableState.STATE_DOCKED: initDockedPopUp(popup); break; case DockableState.STATE_HIDDEN: //initAutoHidePopUp(popup); break; case DockableState.STATE_MAXIMIZED: initMaximizedPopUp(popup); break; case DockableState.STATE_FLOATING: initFloatingPopUp(popup); break; default: // nothing to do } DockableActionCustomizer customizer = target.getDockKey().getActionCustomizer(); if (customizer != null && customizer.isSingleDockableTitleBarPopUpCustomizer()){ if (popup.getComponentCount() > 0){ popup.addSeparator(); } customizer.visitSingleDockableTitleBarPopUp(popup, target); } if (popup.getComponentCount() > 0){ popup.show(tabHeader, e.getX(), e.getY()); this.currentPopUp = popup; } } private JMenuItem createPopUpItem(String text, Icon icon, String tooltip, String actionCommand, KeyStroke accelerator){ JMenuItem menuItem = new JMenuItem(text, icon); menuItem.setActionCommand(actionCommand); menuItem.addActionListener(actionListener); if (accelerator != null){ menuItem.setAccelerator(accelerator); } return menuItem; } /** Init the popup displayed as the title bar contextual menu */ protected void initMaximizedPopUp(JPopupMenu popup){ popup.add(createPopUpItem(RESTORE_TEXT, restoreIcon, RESTORE_TEXT, "maximize", (KeyStroke)UIManager.get("DockingDesktop.maximizeActionAccelerator") )); } protected void initAutoHidePopUp(JPopupMenu popup){ if (DockingUtilities.isChildOfCompoundDockable(getDockable())){ // restore option not allowed for children of a compound dockable } else { popup.add(createPopUpItem(RESTORE_TEXT, dockIcon, RESTORE_TEXT, "dock", (KeyStroke)UIManager.get("DockingDesktop.dockActionAccelerator"))); } if (getDockable().getDockKey().isCloseEnabled()){ popup.add(createPopUpItem(CLOSE_TEXT, closeSmartIcon, CLOSE_TEXT, "close", (KeyStroke)UIManager.get("DockingDesktop.closeActionAccelerator"))); } } protected void initDockedPopUp(JPopupMenu popup){ DockKey key = getDockable().getDockKey(); if (key.isAutoHideEnabled()){ popup.add(createPopUpItem(ICONIFY_TEXT, hideSmartIcon, ICONIFY_TEXT, "dock", (KeyStroke)UIManager.get("DockingDesktop.dockActionAccelerator"))); } if (key.isFloatEnabled()){ popup.add(createPopUpItem(FLOAT_TEXT, floatSmartIcon, FLOAT_TEXT, "float", (KeyStroke)UIManager.get("DockingDesktop.floatActionAccelerator"))); } if (key.isMaximizeEnabled()){ popup.add(createPopUpItem(MAXIMIZE_TEXT, maximizeSmartIcon, MAXIMIZE_TEXT, "maximize", (KeyStroke)UIManager.get("DockingDesktop.maximizeActionAccelerator"))); } if (key.isCloseEnabled()){ popup.add(createPopUpItem(CLOSE_TEXT, closeSmartIcon, CLOSE_TEXT, "close", (KeyStroke)UIManager.get("DockingDesktop.closeActionAccelerator"))); } } /** Init the popup displayed as the title bar contextual menu */ protected void initFloatingPopUp(JPopupMenu popup){ if (DockingUtilities.isChildOfCompoundDockable(getDockable())){ // attach option not allowed for children of a compound dockable } else { popup.add(createPopUpItem(ATTACH_TEXT, attachIcon, ATTACH_TEXT, "float", (KeyStroke)UIManager.get("DockingDesktop.floatActionAccelerator"))); } } /** This method is invoked to hide the pop-up that could still be visible * (To avoid a visible pop-up for an invisible component) */ public void closePopUp(){ if (currentPopUp != null){ currentPopUp.setVisible(false); // @todo uncertain about correct gc of the pop-up in that case currentPopUp = null; } } private void dockAction() { if (isAutoHide()){ desktop.setAutoHide(getDockable(), false); } else { desktop.setAutoHide(getDockable(), true); } } protected void maximizeAction(){ if (isMaximized()) { desktop.restore(getDockable()); } else { desktop.maximize(getDockable()); } } private void closeAction() { desktop.close(getDockable()); } private void floatAction() { if (getDockable().getDockKey().getDockableState() == DockableState.STATE_FLOATING){ desktop.setFloating(getDockable(), true); } else { desktop.setFloating(getDockable(), false); } } private boolean isAutoHide(){ return getDockable().getDockKey().getDockableState() == DockableState.STATE_HIDDEN; } private boolean isMaximized(){ return getDockable().getDockKey().getDockableState() == DockableState.STATE_MAXIMIZED; } protected void configureFloatButton() { if (isFloatButtonDisplayed){ floatSmartIcon.setIcon(UIManager.getIcon("DockViewTitleBar.float")); floatSmartIcon.setPressedIcon(UIManager.getIcon("DockViewTitleBar.float.pressed")); floatSmartIcon.setRolloverIcon(UIManager.getIcon("DockViewTitleBar.float.rollover")); // add a tooltip floatAction.putValue(AbstractAction.SHORT_DESCRIPTION, UIManager.get("DockViewTitleBar.floatButtonText")); } } protected void configureMaximizeButton() { if (isMaximizeButtonDisplayed){ maximizeSmartIcon.setIcon(UIManager.getIcon("DockViewTitleBar.maximize")); maximizeSmartIcon.setPressedIcon(UIManager.getIcon("DockViewTitleBar.maximize.pressed")); maximizeSmartIcon.setRolloverIcon(UIManager.getIcon("DockViewTitleBar.maximize.rollover")); // add a tooltip maximizeAction.putValue(AbstractAction.SHORT_DESCRIPTION, UIManager.get("DockViewTitleBar.maximizeButtonText")); } } protected void configureHideButton() { if (isHideButtonDisplayed){ hideSmartIcon.setIcon(UIManager.getIcon("DockViewTitleBar.hide")); hideSmartIcon.setPressedIcon(UIManager.getIcon("DockViewTitleBar.hide.pressed")); hideSmartIcon.setRolloverIcon(UIManager.getIcon("DockViewTitleBar.hide.rollover")); // add a tooltip hideAction.putValue(AbstractAction.SHORT_DESCRIPTION, UIManager.get("DockViewTitleBar.minimizeButtonText")); } } protected void configureCloseButton() { if (isCloseButtonDisplayed){ closeSmartIcon.setIcon(UIManager.getIcon("DockTabbedPane.close")); closeSmartIcon.setPressedIcon(UIManager.getIcon("DockTabbedPane.close.pressed")); closeSmartIcon.setRolloverIcon(UIManager.getIcon("DockTabbedPane.close.rollover")); // add a tooltip closeAction.putValue(AbstractAction.SHORT_DESCRIPTION, UIManager.get("DockTabbedPane.closeButtonText")); } } public void setDockable(Dockable d){ // overriden to disable DockView settings } public void setDockableAsTab(final Dockable d){ this.dockable = d; if (title != null){ // still needed as removeing it triggers Exception... we'll have to // remove it one day (when building a proper ui class) title.setDockable(dockable); } resetTabIcons(); // allow resizing of split pane beyond minimum size // could be replaced by adding a JScrollPane instead of panels setMinimumSize(new Dimension(30,30)); } public void resetTabIcons(){ ArrayList icons = new ArrayList(); DockKey k = getDockable().getDockKey(); if (k.isCloseEnabled() && isCloseButtonDisplayed){ icons.add(closeSmartIcon); } if (k.isMaximizeEnabled() && isMaximizeButtonDisplayed){ icons.add(maximizeSmartIcon); } if (k.isAutoHideEnabled()&& isHideButtonDisplayed){ icons.add(hideSmartIcon); } if (k.isFloatEnabled() && isFloatButtonDisplayed){ icons.add(floatSmartIcon); } // this is an attempt to create the set of icons displayed for this dockable // currently, only "close" is managed, but other buttons could be added, as // the jTabebdPaneSmartIcon supports(simulates) many sub-buttons. if (icons.size()> 0){ SmartIconJButton [] iconsArray = (SmartIconJButton[]) icons.toArray(new SmartIconJButton[0]); smartIcon = new JTabbedPaneSmartIcon(k.getIcon(), k.getName(), iconsArray); smartIcon.setIconForTabbedPane(tabHeader); tabHeader.addTab("", smartIcon, getDockable().getComponent()); } else { tabHeader.addTab(k.getName(), k.getIcon(), getDockable().getComponent()); } } /** {@inheritDoc} */ public void installDocking(DockingDesktop desktop) { this.desktop = desktop; desktop.installDockableDragSource(tabHeader); dockable.getDockKey().addPropertyChangeListener(keyListener); } /** {@inheritDoc} */ public void uninstallDocking(DockingDesktop desktop) { desktop.uninstallDockableDragSource(tabHeader); dockable.getDockKey().removePropertyChangeListener(keyListener); } public String getUIClassID() { return "PanelUI"; // default panel UI } protected TabHeader createTabHeader(){ return new TabHeader(); } protected class TabHeader extends JTabbedPane implements DockableDragSource { public boolean startDragComponent(Point p) { Rectangle bounds = getBoundsAt(0); return bounds.contains(p); } public Container getDockableContainer() { return DockViewAsTab.this; } public Dockable getDockable() { return dockable; } public void endDragComponent(boolean dropped) { } } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/DockViewTitleBar.java0000644000175000017500000007160010573516350026247 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking; import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.beans.*; import java.beans.PropertyChangeEvent; import java.awt.event.MouseEvent; import java.awt.Component; import java.awt.Point; import java.util.*; /** A title bar, associated to a DockView (container of a single user component). *

* Here is an example of a title bar : . *

* DockViewTitleBar is able to display the following properties of a DockKey : *

*

* This title bar supports buttons used for docking features : * * * * * * * * *
function Version 1.1Version 2.0
maximize
restore
hide
dock
close
float (detach)n/a
attachn/a
* *

* The buttons managed have no effect on the state of the dockable : they just fire * property change events, and it is the responsibility of the DockableContainer to * listen to those events and to relay the operation to the docking desktop. *

* Note : the UI Delegate of the DockViewTitleBar is the {@link com.vlsolutions.swing.docking.ui.DockViewTitleBarUI} * * @author Lilian Chamontin, vlsolutions. * @version 1.0 */ public class DockViewTitleBar extends JPanel implements DockableDragSource { /** Property name designating the autohide button selection */ public static final String PROPERTY_AUTOHIDE = "DockTitle.AUTOHIDE"; /** Property name designating the close button selection */ public static final String PROPERTY_CLOSED = "DockTitle.CLOSED"; /** Property name designating a drag gesture beginning */ public static final String PROPERTY_DRAGGED = "DockTitle.DRAGGED"; /** Property name designating the maximized button selection */ public static final String PROPERTY_MAXIMIZED = "DockTitle.MAXIMIZED"; /** Property name designating the float button selection */ public static final String PROPERTY_FLOAT = "DockTitle.FLOAT"; private static final String uiClassID = "DockViewTitleBarUI"; private static final String CLOSE_TEXT = UIManager.getString("DockViewTitleBar.closeButtonText"); private static final String ICONIFY_TEXT = UIManager.getString("DockViewTitleBar.minimizeButtonText"); private static final String RESTORE_TEXT = UIManager.getString("DockViewTitleBar.restoreButtonText"); private static final String MAXIMIZE_TEXT = UIManager.getString("DockViewTitleBar.maximizeButtonText"); private static final String FLOAT_TEXT = UIManager.getString("DockViewTitleBar.floatButtonText"); private static final String ATTACH_TEXT = UIManager.getString("DockViewTitleBar.attachButtonText"); private static Icon closeIcon = UIManager.getIcon("DockViewTitleBar.menu.close"); private static Icon maximizeIcon = UIManager.getIcon("DockViewTitleBar.menu.maximize"); private static Icon restoreIcon = UIManager.getIcon("DockViewTitleBar.menu.restore"); private static Icon hideIcon = UIManager.getIcon("DockViewTitleBar.menu.hide"); private static Icon dockIcon = UIManager.getIcon("DockViewTitleBar.menu.dock"); private static Icon floatIcon = UIManager.getIcon("DockViewTitleBar.menu.float"); private static Icon attachIcon = UIManager.getIcon("DockViewTitleBar.menu.attach"); // ------------ member fields -------------- // this creation tricks to manage the UI class requiring access to the components // before they are created private JLabel titleLabel = getTitleLabel(); private JButton closeButton = getCloseButton(); private JButton dockButton = getHideOrDockButton(); private JButton maximizeButton = getMaximizeOrRestoreButton(); private JButton floatButton = getFloatButton(); private boolean active; private ActionListener actionListener = new ActionListener(){ public void actionPerformed(ActionEvent e){ if (e.getActionCommand().equals("dock")){ dockAction(); } else if (e.getActionCommand().equals("close")){ closeAction(); } else if (e.getActionCommand().equals("maximize")){ maximizeAction(); } else if (e.getActionCommand().equals("float")){ floatAction(); } } }; private Dockable target; // the component this title is for /** used to have a state of blinking (notification) */ private boolean isNotification = false; private JPopupMenu currentPopUp = null; /** current blinking count (the limit to the notification timer) */ private int blinkCount = 0; private int MAX_BLINKS = UIManager.getInt("DockingDesktop.notificationBlinkCount"); /** reacts to single and double click on title bar */ private MouseListener titleMouseListener = new MouseAdapter() { public void mouseClicked(MouseEvent e) { if (e.getClickCount() == 2) { maximizeAction(); } else { //requestFocus(); // replaced by a better focus behaviour for 1.2 target.getComponent().requestFocus(); } } public void mousePressed(MouseEvent e){ if (e.isPopupTrigger()){ checkForPopUp(e); } } public void mouseReleased(MouseEvent e){ if (e.isPopupTrigger()){ checkForPopUp(e); } } }; /** listen to the key changes */ private PropertyChangeListener dockKeyListener = new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent e) { String pName = e.getPropertyName(); if (pName.equals(DockKey.PROPERTY_ICON)) { titleLabel.setIcon( (Icon) e.getNewValue()); } else if (pName.equals(DockKey.PROPERTY_NAME)) { titleLabel.setText( (String) e.getNewValue()); revalidate(); } else if (pName.equals(DockKey.PROPERTY_TOOLTIP)) { setToolTipText( (String) e.getNewValue()); } else if (pName.equals(DockKey.PROPERTY_NOTIFICATION)) { // attract user attention boolean isOn = ( (Boolean) e.getNewValue()).booleanValue(); if (isOn && !isActive()) { if (notificationTimer == null) { notificationTimer = new javax.swing.Timer(1000, new ActionListener() { public void actionPerformed(ActionEvent actionEvent) { setNotification(!isNotification); if (!isNotification){ blinkCount ++; if (blinkCount >= MAX_BLINKS){ blinkCount = 0; notificationTimer.stop(); // enough blinking } } } }); } notificationTimer.restart(); } else { if (notificationTimer != null) { notificationTimer.stop(); blinkCount = 0; } setNotification(false); } } /*else if (pName.equals(DockKey.PROPERTY_DOCKABLE_STATE)){ * int newState = ((Integer)e.getNewValue()).intValue(); int oldState = ((Integer)e.getOldValue()).intValue(); switch (newState){ case DockableState.STATE_HIDDEN : setAutoHide(true); break; case DockableState.STATE_MAXIMIZED : setMaximized(true); break; case DockableState.STATE_DOCKED : if (oldState == DockableState.STATE_HIDDEN){ setAutoHide(false); } break; default: //@todo : managed the floatable state // nothing to track here } }*/ } }; /** Timer used to trigger repaint event for notification (blinking title bar) */ private javax.swing.Timer notificationTimer; /** singleton for keyboard management */ private static FocusHighlighter focusHighlighter = new FocusHighlighter(); //2005/11/10 private DockingDesktop desktop; /** Constructs an empty title bar (no dockable yet associated). */ public DockViewTitleBar() { this(null); } /** Constructs a title bar for the specified dockable. *

* Warning : a DockViewTitleBar can be used with multiple dockables (this is the case * for example in autohide borders, where a single titlebar is shared by all hidden dockables * (shown only when one is expanding). */ public DockViewTitleBar(Dockable dockable) { setDockable(dockable); setLayout(new BoxLayout(this, BoxLayout.X_AXIS)); setOpaque(true); closeButton.setText(""); dockButton.setText(""); maximizeButton.setText(""); closeButton.setActionCommand("close"); dockButton.setActionCommand("dock"); maximizeButton.setActionCommand("maximize"); floatButton.setActionCommand("float"); closeButton.addActionListener(actionListener); dockButton.addActionListener(actionListener); maximizeButton.addActionListener(actionListener); floatButton.addActionListener(actionListener); this.addMouseListener(titleMouseListener); //maximizeButton.addMouseListener(new ButtonRolloverEffect()); } /** Returns the desktop associated to this title bar, if one has been registered * with #installDocking(DockingDesktop), or null. */ public DockingDesktop getDesktop(){ return desktop; } /** Overriden as a means to unregister internal listeners, do not call directly */ public void removeNotify(){ super.removeNotify(); /* KeyboardFocusManager.getCurrentKeyboardFocusManager().removePropertyChangeListener( focusHighlighter); 2005/11/10: now it's shared between title bars*/ if (target != null){ target.getDockKey().removePropertyChangeListener(dockKeyListener); } } /** called to build the title bar */ protected void layoutTitleBar(){ removeAll(); add(Box.createHorizontalStrut(4)); // keep the label not to close to the border add(titleLabel); add(Box.createHorizontalGlue()); int height = UIManager.getInt("DockViewTitleBar.height"); add(Box.createRigidArea(new Dimension(4,height))); // fixed height add(dockButton); add(floatButton); add(maximizeButton); add(closeButton); } /** Returns the label used to display the dockkey name. *

Shouldn't be used to update the title : the best way is to update the * DockKey (property listener ensure the labels and buttons stay in sync). * *@since 2.0 */ public JLabel getTitleLabel(){ if (titleLabel == null){ titleLabel = new JLabel(); } return titleLabel; } public JButton getCloseButton(){ if (closeButton == null){ closeButton = new JButton(); } return closeButton; } /** returns the button used for hiding or docking the view. *

* As hiding and docking are mutually exclusive, the same button is used for both purposes */ public JButton getHideOrDockButton(){ if (dockButton == null){ dockButton = new JButton(); } return dockButton; } /** returns the button used for maximizing or restoring the view. *

* As those operations are mutually exclusive, the same button is used for both purposes */ public JButton getMaximizeOrRestoreButton(){ if (maximizeButton == null){ maximizeButton = new JButton(); } return maximizeButton; } /** returns the button used for floating (detach) the view. */ public JButton getFloatButton(){ if (floatButton == null){ floatButton = new JButton(); } return floatButton; } private void setNotification(boolean notification) { boolean old = this.isNotification; this.isNotification = notification; firePropertyChange("titlebar.notification", old, notification); } private boolean isAutoHide(){ return target.getDockKey().getDockableState() == DockableState.STATE_HIDDEN; } private boolean isMaximized(){ return target.getDockKey().getDockableState() == DockableState.STATE_MAXIMIZED; } private void dockAction() { boolean old = isAutoHide(); firePropertyChange(PROPERTY_AUTOHIDE, old, !old); } private void maximizeAction() { // we use the visible property of the button to check if maximization // is enabled or not if (maximizeButton.isVisible()){ boolean old = isMaximized(); // we don't really change the maximized property, // which will be updated if the desktop accepts this maximization /* We do not use fireVetoableChange, to keep maximization processing outside * the title bar (everything is driven par the dockingdesktop and the * SingleDockableContainer */ firePropertyChange(PROPERTY_MAXIMIZED, old, !old); } } private void closeAction() { firePropertyChange(PROPERTY_CLOSED, false, true); } private void floatAction() { if (target.getDockKey().getDockableState() == DockableState.STATE_FLOATING){ firePropertyChange(PROPERTY_FLOAT, true, false); } else { firePropertyChange(PROPERTY_FLOAT, false, true); } } /** This method is invoked to hide the pop-up that could still be visible * (To avoid a visible pop-up for an invisible component) */ public void closePopUp(){ if (currentPopUp != null){ currentPopUp.setVisible(false); // @todo uncertain about correct gc of the pop-up in that case currentPopUp = null; } } /** {@inheritDoc} * @since 2.0 */ public String getUIClassID() { return uiClassID; } /** Returns true if the dockable is the currently active one. *

* There is at most one active dockable for a dekstop, and it there is one, * it is the one which contains the keybord focused component. * */ public boolean isActive() { return active; } /** Updates the active property. * A title bar is active when the dockable it is for is ancestor of * the keybord focused component. * */ public void setActive(boolean active) { boolean old = this.active; this.active = active; firePropertyChange("active", old, active); } /** Changes the dockable this title bar is for */ public void setDockable(Dockable dockable) { Dockable old = target; if (target != null && target != dockable) { target.getDockKey().removePropertyChangeListener(dockKeyListener); } if (dockable != null) { this.target = dockable; layoutTitleBar(); DockKey key = dockable.getDockKey(); titleLabel.setText(key.getName()); titleLabel.setIcon(key.getIcon()); setToolTipText(key.getTooltip()); revalidate(); /*dockButton.setVisible(key.isAutoHideEnabled()); this.autoHide = key.getDockableState() == DockableState.STATE_HIDDEN; setDockButtonAsAutoHide(autoHide); closeButton.setVisible(key.isCloseEnabled()); maximizeButton.setVisible(key.isMaximizeEnabled() && !autoHide);*/ key.addPropertyChangeListener(dockKeyListener); } firePropertyChange("dockable", old, dockable); } /** {@inheritDoc} */ public Dockable getDockable() { return target; } /** {@inheritDoc} */ public boolean startDragComponent(Point p) { // disable DnD for some cases : // - child of a compound dockable, in hidden state // - child of a maximized compund dockable // - maximized dockable int targetState = target.getDockKey().getDockableState(); if (targetState == DockableState.STATE_HIDDEN){ if (DockingUtilities.isChildOfCompoundDockable(target)){ // nested hidden dockables cannot be drag and dropped return false; } } else if (targetState == DockableState.STATE_DOCKED){ boolean isChildOfMaximizedContainer = false; if (desktop != null){ Dockable max = desktop.getMaximizedDockable(); if (max != null && max.getComponent().getParent().isAncestorOf(this)){ isChildOfMaximizedContainer = true; } } if (isChildOfMaximizedContainer){ return false; } } else if (targetState == DockableState.STATE_MAXIMIZED){ return false; } // notify our listeners that drag has begun firePropertyChange(PROPERTY_DRAGGED, false, true); return true; } /** Returns a readeable String representing this title bar */ public String toString() { if (target != null) { return "DockViewTitleBar of [" + target.getDockKey() + "]"; } else { return "DockViewTitleBar"; } } private JMenuItem createPopUpItem(String text, Icon icon, String tooltip, String actionCommand, KeyStroke accelerator){ JMenuItem menuItem = new JMenuItem(text, icon); menuItem.setActionCommand(actionCommand); menuItem.addActionListener(actionListener); if (accelerator != null){ menuItem.setAccelerator(accelerator); } return menuItem; } private void checkForPopUp(MouseEvent e){ JPopupMenu popup = new JPopupMenu(target.getDockKey().getName()); // first add the standard menu DockKey key = target.getDockKey(); switch (key.getDockableState()){ case DockableState.STATE_DOCKED: initDockedPopUp(popup); break; case DockableState.STATE_HIDDEN: initAutoHidePopUp(popup); break; case DockableState.STATE_MAXIMIZED: initMaximizedPopUp(popup); break; case DockableState.STATE_FLOATING: initFloatingPopUp(popup); break; default: // nothing to do } DockableActionCustomizer customizer = target.getDockKey().getActionCustomizer(); if (customizer != null && customizer.isSingleDockableTitleBarPopUpCustomizer()){ if (popup.getComponentCount() > 0){ popup.addSeparator(); } customizer.visitSingleDockableTitleBarPopUp(popup, target); } if (popup.getComponentCount() > 0){ popup.show(DockViewTitleBar.this, e.getX(), e.getY()); this.currentPopUp = popup; } } /** Init the popup displayed as the title bar contextual menu */ protected void initMaximizedPopUp(JPopupMenu popup){ popup.add(createPopUpItem(RESTORE_TEXT, restoreIcon, RESTORE_TEXT, "maximize", (KeyStroke)UIManager.get("DockingDesktop.maximizeActionAccelerator") )); } protected void initAutoHidePopUp(JPopupMenu popup){ if (DockingUtilities.isChildOfCompoundDockable(target)){ // restore option not allowed for children of a compound dockable } else { popup.add(createPopUpItem(RESTORE_TEXT, dockIcon, RESTORE_TEXT, "dock", (KeyStroke)UIManager.get("DockingDesktop.dockActionAccelerator"))); } if (target.getDockKey().isCloseEnabled()){ popup.add(createPopUpItem(CLOSE_TEXT, closeIcon, CLOSE_TEXT, "close", (KeyStroke)UIManager.get("DockingDesktop.closeActionAccelerator"))); } } protected void initDockedPopUp(JPopupMenu popup){ DockKey key = target.getDockKey(); if (key.isAutoHideEnabled()){ popup.add(createPopUpItem(ICONIFY_TEXT, hideIcon, ICONIFY_TEXT, "dock", (KeyStroke)UIManager.get("DockingDesktop.dockActionAccelerator"))); } if (key.isFloatEnabled()){ popup.add(createPopUpItem(FLOAT_TEXT, floatIcon, FLOAT_TEXT, "float", (KeyStroke)UIManager.get("DockingDesktop.floatActionAccelerator"))); } if (key.isMaximizeEnabled()){ popup.add(createPopUpItem(MAXIMIZE_TEXT, maximizeIcon, MAXIMIZE_TEXT, "maximize", (KeyStroke)UIManager.get("DockingDesktop.maximizeActionAccelerator"))); } if (key.isCloseEnabled()){ popup.add(createPopUpItem(CLOSE_TEXT, closeIcon, CLOSE_TEXT, "close", (KeyStroke)UIManager.get("DockingDesktop.closeActionAccelerator"))); } } /** Init the popup displayed as the title bar contextual menu */ protected void initFloatingPopUp(JPopupMenu popup){ if (DockingUtilities.isChildOfCompoundDockable(target)){ // attach option not allowed for children of a compound dockable } else { popup.add(createPopUpItem(ATTACH_TEXT, attachIcon, ATTACH_TEXT, "float", (KeyStroke)UIManager.get("DockingDesktop.floatActionAccelerator"))); } } /** Returns the container of the dockable's component */ public Container getDockableContainer() { // easy return getParent(); } public void installDocking(DockingDesktop desktop) { this.desktop = desktop; } public void uninstallDocking(DockingDesktop desktop){ this.desktop = null; } /** notifies the source when the drag operation has ended (by a drop or cancelled) * @since 2.1.3 */ public void endDragComponent(boolean dropped){ // nothing more to do } /* used to highlight the title bar when its parent is ancestor of the * focused component */ private static class FocusHighlighter implements PropertyChangeListener { private DockViewTitleBar activeTitleBar; FocusHighlighter(){ // this is a singleton so we register here for keyboard focus events properties KeyboardFocusManager.getCurrentKeyboardFocusManager().addPropertyChangeListener( "focusOwner", this); } // focusOwner public void propertyChange(PropertyChangeEvent e) { Component c = (Component) e.getNewValue(); Component ancestor = c; // is the focus contained in a single dockable container while(ancestor != null && !(ancestor instanceof SingleDockableContainer) ){ ancestor = ancestor.getParent(); } if (ancestor != null){ if (ancestor instanceof DockView){ DockView view = (DockView) ancestor; DockViewTitleBar tb = view.getTitleBar(); if (tb == activeTitleBar){ // no view change in focus } else if (tb != null){ if (activeTitleBar != null){ activeTitleBar.setActive(false); } tb.setActive(true); // reset notification (blinking) Dockable target = tb.target; if (target != null && target.getDockKey() != null){ //2007/02/27 fixed NPE target.getDockKey().setNotification(false); } } else { // tb == null && tb != activeTitleBar activeTitleBar.setActive(false); } activeTitleBar = tb; } else if (ancestor instanceof AutoHideExpandPanel){ DockViewTitleBar tb = ((AutoHideExpandPanel)ancestor).getTitleBar(); if (tb == activeTitleBar){ // no view change in focus } else if (tb != null){ if (activeTitleBar != null){ activeTitleBar.setActive(false); } tb.setActive(true); // reset notification (blinking) tb.target.getDockKey().setNotification(false); } else { // tb == null && tb != activeTitleBar activeTitleBar.setActive(false); } activeTitleBar = tb; } else { if (activeTitleBar != null){ activeTitleBar.setActive(false); } activeTitleBar = null; } } else { if (activeTitleBar != null){ activeTitleBar.setActive(false); } activeTitleBar = null; } /* // try to find if the component taking the focus is the ancestor if (activeTitleBar != null){ Container parent = activeTitleBar.getParent(); if (parent != null && c != null && parent.isAncestorOf(c)) { if (!active) { setActive(true); } // reset notification (blinking) target.getDockKey().setNotification(false); } else if (active) { setActive(false); } */ } } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/Dockable.java0000644000175000017500000001305410573516350024610 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking; import java.awt.*; /** Interface describing a component (AWT/Swing) that can be managed by the * DockingDesktop. * *

* Objects implementing this interface are usually wrappers around user components, * or user components themselves. *

* * @author Lilian Chamontin, vlsolutions. * @version 1.0 * */ public interface Dockable { /** returns the unique key identifying the docked element */ public DockKey getDockKey(); /** returns the component wrapped. * * */ public Component getComponent(); } vldocking_2.1.4/src/com/vlsolutions/swing/docking/DockableActionCustomizer.java0000644000175000017500000001737110573516350030041 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking; import javax.swing.JPopupMenu; /** An objet that can provide actions relative to a dockable. *

* It can be used, for example, to add a set of menu items to the contextual menu * associated with any dockable. *

Example : *

 *   DockableActionCustomizer customizer = new DockableActionCustomizer(){
 *     public void visitSingleDockableTitleBarPopUp(JPopupMenu popUpMenu, Dockable dockable){
 *        popUpMenu.add(new JMenuItem("test")); // a menu for SingleDockableContainers
 *     }
 *     public void visitTabSelectorPopUp(JPopupMenu popUpMenu, Dockable dockable){
 *          popUpMenu.add(new JMenuItem(closeAllInTab)); // two menus when contained in a tabbed container
 *          popUpMenu.add(new JMenuItem(closeAllOtherInTab));
 *     }
 *   };
 *   customizer.setSingleDockableTitleBarPopUpCustomizer(true); // enable single
 *   customizer.setTabSelectorPopUpCustomizer(true); // enable tabbed
 *   DockKey key = ...
 *   key.setActioncustomizer(customizer); // assoiate it with one or more DockKeys
 * 
*

* Implementation Note : the customizer is invoked every time a pop-up is triggered * from the associated dockable container. It is a good practice to keep object creation * and listener attachments outside the visit..() methods. * * @author Lilian Chamontin, VLSolutions */ public class DockableActionCustomizer { private boolean isSingleDockableTitleBarPopUpCustomizer = false; private boolean isTabSelectorPopUpCustomizer = false; /** Default constructor */ public DockableActionCustomizer() { } /** Override this method to add contextual items at the end of the pop-up menu * which can be triggered on a tab selector. *

* It is recommended to add menu items at the end to the pop-up menu as other * items may have been installed by other visitors (DockGroup for example) *

* implementation note : This method can be called multiple times as pop-up menus are built during * the contextual event dispatch (not stored for the life of the dockable). * */ public void visitTabSelectorPopUp(JPopupMenu popUpMenu, Dockable tabbedDockable){ } /** Override this method to add contextual items at the end of the pop-up menu * which can be triggered on the title bar of a single dockable. *

* It is recommended to add menu items at the end to the pop-up menu as other * items may have been installed by other visitors (DockGroup for example) *

* implementation note : This method can be called multiple times as pop-up menus are built during * the contextual event dispatch (not stored for the life of the dockable). * */ public void visitSingleDockableTitleBarPopUp(JPopupMenu popUpMenu, Dockable dockable){ } /** Returns wether this customizer is used in the context of a SingleDockableContainer */ public boolean isSingleDockableTitleBarPopUpCustomizer(){ return this.isSingleDockableTitleBarPopUpCustomizer; } /** Updates the singleDockableTitleBar property. * @see #isSingleDockableTitleBarPopUpCustomizer() */ public void setSingleDockableTitleBarPopUpCustomizer(boolean isCustomizer){ this.isSingleDockableTitleBarPopUpCustomizer = isCustomizer; } /** Returns wether this customizer is used in the context of a TabbedDockableContainer */ public boolean isTabSelectorPopUpCustomizer(){ return this.isTabSelectorPopUpCustomizer; } /** Updates the tabSelectorDockableTitleBar property * @see #isTabSelectorPopUpCustomizer() */ public void setTabSelectorPopUpCustomizer(boolean isCustomizer){ this.isTabSelectorPopUpCustomizer = isCustomizer; } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/DockableContainer.java0000644000175000017500000001313510573516350026453 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking; /** A DockableContainer is the base interface of GUI components used to * display Dockable components. *

* The components are usually displayed with decorations * (a title bar, docking state management buttons, a drop shadow, ...) *

* This interface is meant for API extenders that would like to create new kind of * containers (via the sub-interfaces {@link SingleDockableContainer} * and {@link TabbedDockableContainer} and the {@link DockableContainerFactory}). *

* Usually, a DockableContainer also contains (or implements) one ore more * DockableDragSources * in order to achieve drag and drop operations. *

* * @see DockableDragSource * @see DockableContainerFactory * @author Lilian Chamontin, vlsolutions. * @version 1.0 */ public interface DockableContainer { /** Invoked once after creation, in order to let this component register * its DockableDragSources to the DockingDesktop, and have a reference of this * Desktop. * *

basic implementation use a single DragSource, and thus calls * desk.installDockableDragSource(dragSource). * * * */ public void installDocking(DockingDesktop desktop); /** Called once, when the dockablecontainer is no longer used by the desktop, * in order to releases resources and listeners taken on installDocking(). * */ public void uninstallDocking(DockingDesktop desktop); } vldocking_2.1.4/src/com/vlsolutions/swing/docking/DockableContainerFactory.java0000644000175000017500000001652110573516350030005 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking; import java.awt.Window; /** An abstract factory used by the DockingDesktop to create instance * of Dockable containers. *

* This factory enables API Extenders to change part of the behaviour on the DockingDesktop * (mostly about look and feel issues) without modifying the code of that central class. * * @see DockableContainer * @see DefaultDockableContainerFactory : the default implementation * * @author Lilian Chamontin, vlsolutions. * @version 1.1 * @update 2007/01/08 Lilian Chamontin : updated to declare a new titlebar factory method * */ public abstract class DockableContainerFactory { private static DockableContainerFactory factory; /** Constant used to describe the type of usage a SingleDockableContainer is for*/ public static final int PARENT_DESKTOP = 0; /** Constant used to describe the type of usage a SingleDockableContainer is for*/ public static final int PARENT_TABBED_CONTAINER = 1; /** Constant used to describe the type of usage a SingleDockableContainer is for*/ public static final int PARENT_SPLIT_CONTAINER = 2; /** Constant used to describe the type of usage a SingleDockableContainer is for*/ public static final int PARENT_DETACHED_WINDOW = 3; /** This method is called by the DockingDesktop whenever a dockable is inserted * in its containment hierachy. * */ public abstract SingleDockableContainer createDockableContainer(Dockable dockable, int parentType); /** @deprecated use the other createDockableContainer method ({@link #createDockableContainer(Dockable, int)} */ public SingleDockableContainer createDockableContainer(Dockable dockable, boolean c){ return createDockableContainer(dockable, PARENT_SPLIT_CONTAINER); } /** This method is called when a tab insertion is requested by the DockingDesktop. */ public abstract TabbedDockableContainer createTabbedDockableContainer(); /** This method is called when a dockable is detached from the DockingDesktop and put * in the FLOATING state. *

* The floating container must be an instanceof Dialog or Window. */ public abstract FloatingDockableContainer createFloatingDockableContainer(Window owner); /** This method is invoked when a dockable container needs to install a title bar. *

* This method is used by the standard implementation of Docking (DockView, etc) but is optional * for other implementations, as currently the titlebar isn't specified as a core component of * the docking framework (i.e. it is not an interface). *@since 2.1.3 */ public abstract DockViewTitleBar createTitleBar(); /** Returns the current factory. *

it no factory has been provided, it will * fall back on DefaultDockableContainerFactory */ public static DockableContainerFactory getFactory(){ if (factory == null){ factory = new DefaultDockableContainerFactory(); } return factory; } /** Changes the factory to be used by DockingDesktop. *

* Note that this change is not propagated to already docked components. * */ public static void setFactory(DockableContainerFactory f){ factory = f; } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/DockableDragSource.java0000644000175000017500000001351610573516350026572 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking; import java.awt.*; /** An interface implemented by visual components used for drag and drop operations * on a DockableContainer. *

* This interface is used by API Extenders to create new kind of drag sources. *

* A "Drag Source" is a component, linked to a Dockable, responsible * for drag gesture recognition. There can be more than one DockableDragSource per * Dockable. *

* For example, the title bar of a docked component is usually the drag source of * this component (meaning : when a user drags the title bar, he expects the dockable * to be dragged around). *

* These draggable components must be able to give informations about their * target (the component known to the user, which is actually dragged). * * @author Lilian Chamontin, vlsolutions. * @version 1.0 */ public interface DockableDragSource { /** Notifies this source that a drag operation has begun. *

The source may reject the drag according to internal conditions (in that case * this method shall return false) or to wrong mouse position . * * @return true if drag operation is accepted (i.e the zone pointed by p refers to * a draggable component), false otherwise. * */ public boolean startDragComponent(Point p); /** Returns the Dockable component this source is for */ public Dockable getDockable(); /** returns the DockableContainer responsible for displaying the associated dockable */ public Container getDockableContainer(); /** notifies the source when the drag operation has ended (by a drop or cancelled) * @since 2.1.3 */ public void endDragComponent(boolean dropped); } vldocking_2.1.4/src/com/vlsolutions/swing/docking/DockablePanel.java0000644000175000017500000001252610573516350025573 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking; import javax.swing.*; import java.awt.*; /** A basic implementation of Dockable. *

* It's a JPanel with a BorderLayout, and it can display a single Dockable. *

* This class is provided as an intermediary between a User Component and the docking * desktop (for example, for application that don't want to be too tied with the * DockingFramework). * * @author Lilian Chamontin, vlsolutions. * @version 1.0 */ public class DockablePanel extends JPanel implements Dockable{ private DockKey key; public DockablePanel() { setLayout(new BorderLayout()); } public DockablePanel(Component contained, DockKey key) { setLayout(new BorderLayout()); add(contained, BorderLayout.CENTER); this.key = key; } public DockKey getDockKey() { return key; } public void setDockKey(DockKey key){ this.key = key; } public Component getComponent() { return this; } /** Removes all contained components (normally no more than one), and * put this comp on the center area of the BorderLayout. * */ public void setComponent(Component comp) { removeAll(); add(comp, BorderLayout.CENTER); } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/DockableResolver.java0000644000175000017500000000107110573516344026331 0ustar twernertwernerpackage com.vlsolutions.swing.docking; /** An interface used to find a dockable (when read from an input stream like XML) * when the only information given is its DockKey id. * *

This is mainly to allow auto-registration of new dockables when loading a new workspace. * * @author Lilian Chamontin, VLSolutions * @since 2.1.2 */ public interface DockableResolver { /** Returns the dockable which should be associated to this DockKey identifier, or null if * not found. */ public Dockable resolveDockable(String keyName); } vldocking_2.1.4/src/com/vlsolutions/swing/docking/DockableState.java0000644000175000017500000002164610573516350025617 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking; import java.awt.*; /** General information about the current state of a dockable component. *

* This class is a simple record of a dockable and its current display state. *

It is used together with DockableStateChangeEvents (and listeners) to * track changes of Dockable visibility. * * * @author Lilian Chamontin, vlsolutions. * @version 1.0 * * @update 2005/10/07 Lilian Chamontin : added getStateName(int state) method */ public class DockableState implements Comparable { private Dockable dockable; private static final String [] stateNames = {"CLOSED", "DOCKED", "HIDDEN", "MAXIMIZED", "FLOATING"}; /** A constant describing a Dockable that is not visible. * */ public static final int STATE_CLOSED = 0; // only registered /** A constant describing a Dockable that is visible (displayed in a DockableContainer) */ public static final int STATE_DOCKED = 1; /** A constant describing a Dockable that is in auto-hide mode (reduced to a button) */ public static final int STATE_HIDDEN = 2; /** A constant describing a Dockable that is currently maximized */ public static final int STATE_MAXIMIZED = 3; /** A constant describing a Dockable that is currently floating (detached from the desktop) */ public static final int STATE_FLOATING = 4; private int state ; /** Relative position for hidden/closed dockable show-again */ private RelativeDockablePosition position; /** Desktop currently using this dockable */ private DockingDesktop desktop; public DockableState() { position = new RelativeDockablePosition(); } public DockableState(DockingDesktop desktop, Dockable dockable, int state) { this.desktop = desktop; this.dockable = dockable; this.state = state; position = new RelativeDockablePosition(); } public DockableState(DockingDesktop desktop, Dockable dockable, int state, RelativeDockablePosition position) { this.desktop = desktop; this.dockable = dockable; this.state = state; this.position = position; } /** Creates a dockable state based on an existing state, with another relative positionning */ public DockableState(DockableState copy, RelativeDockablePosition position) { this.desktop = copy.desktop; this.dockable = copy.dockable; this.state = copy.state; this.position = position; } /** Comparable interface, used to sort components by name order. * */ public int compareTo(Object object) { if (object instanceof DockableState){ return dockable.getDockKey().getName().compareTo( ( (DockableState) object).dockable.getDockKey().getName()); } else { return -1; } } /** Returns the dockable this state is for */ public Dockable getDockable() { return dockable; } /** Convenience method returning wether the dockable is in the DOCKED state */ public boolean isDocked(){ return state == STATE_DOCKED; } /** Convenience method returning wether the dockable is in the HIDDEN state */ public boolean isHidden(){ return state == STATE_HIDDEN; } /** Convenience method returning wether the dockable is in the CLOSED state */ public boolean isClosed(){ return state == STATE_CLOSED; } /** Convenience method returning wether the dockable is in the FLOATING state */ public boolean isFloating(){ return state == STATE_FLOATING; } /** Convenience method returning wether the dockable is in the MAXIMIZED state */ public boolean isMaximized(){ return state == STATE_MAXIMIZED; } /** Returns the current state of the dockable (CLOSED, DOCKED, HIDDEN...). */ public int getState() { return state; } /** Returns the relative restore position of the dockable when it is not shown (auto-hide * or closed). *

* Please note that this position is meaningless for visible components * (as it is not automatically calculated at every move / resize of the dockable ). * * */ public RelativeDockablePosition getPosition(){ return position; } public String toString(){ return "DockableState [" + dockable.getDockKey() + ", state=" + stateNames[state] + ", position=" + position; } /** Returns a litteral representation of the given state *@since 2.0.1 */ public static String getStateName(int state){ //2005/10/07 return stateNames[state]; } /** Returns the desktop currently using this dockable, or null if none * * @since 2.1 */ public DockingDesktop getDesktop() { return desktop; } /** Updates the desktop field (desktop using this dockable) * @since 2.1 */ public void setDesktop(DockingDesktop desktop) { this.desktop = desktop; } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/DockableStoreButton.java0000644000175000017500000001127510573516344027027 0ustar twernertwernerpackage com.vlsolutions.swing.docking; import com.vlsolutions.swing.docking.event.DockDragEvent; import com.vlsolutions.swing.docking.event.DockDropEvent; import java.awt.Container; import java.awt.Point; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.Icon; import javax.swing.JButton; /** A Button that can be used to store a dockable (for example to allow moving a dockable * between two workspaces). * *

* The button is able to display the Icon, text and toolip of a dockable key, and can be used as a drag * source (to initiate a drop into a desktop). * * @author Lilian Chamontin, VLSolutions */ public class DockableStoreButton extends JButton implements DockDropReceiver, DockableDragSource { private Dockable dockable; private String emptyText = "Nothing stored"; private String emptyTooltip = "Move and drop a view of your application above this button to store it"; private Icon emptyIcon = null; private String fullText = "View &1 stored"; private String fullTooltip = "Drag this button to move the view &1 to a new position"; public DockableStoreButton(String emptyText) { super(emptyText); this.emptyText = emptyText; updateButtonText(); } public DockableStoreButton() { updateButtonText(); } /** when a dockable is dragged above this button, the button stores it as its new * target dockable. * @see #getDockable() */ public void processDockableDrag(DockDragEvent event) { event.rejectDrag(); } /** Rejects the drop as this action isn't possible on this component */ public void processDockableDrop(DockDropEvent event) { setDockable(event.getDragSource().getDockable()); event.rejectDrop(); } public void setDockable(Dockable dockable) { this.dockable = dockable; updateButtonText(); } /** Override this method if you want to change the display (text and icon) of this button and * the default settings don't suit your needs. */ public void updateButtonText(){ if (dockable == null){ setText(emptyText); setToolTipText(emptyTooltip); setIcon(null); } else { String text = fullText.replaceAll("&1", dockable.getDockKey().getName()); setText(text); String tttext = fullTooltip.replaceAll("&1", dockable.getDockKey().getName()); setToolTipText(tttext); setIcon(dockable.getDockKey().getIcon()); } } public boolean startDragComponent(Point p) { return dockable != null; } /** Return the dockable currently stored (may be null) */ public Dockable getDockable() { return dockable; } public Container getDockableContainer() { return (Container) DockingUtilities.findDockableContainer(dockable); } public void endDragComponent(boolean dropped) { if (dropped){ dockable = null; updateButtonText(); } } /** Returns the text used for this button when no dockable is stored*/ public String getEmptyText() { return emptyText; } /** updates the text used for this button when no dockable is stored*/ public void setEmptyText(String emptyText) { this.emptyText = emptyText; } /** Returns the text used as tooltip for this button when no dockable is stored*/ public String getEmptyTooltip() { return emptyTooltip; } /** Updates the text used as tooltip for this button when no dockable is stored*/ public void setEmptyTooltip(String emptyTooltip) { this.emptyTooltip = emptyTooltip; } /** Returns the Icon used with this button when no dockable is selected */ public Icon getEmptyIcon() { return emptyIcon; } /** Updates the icon used for this button when no dockable is stored*/ public void setEmptyIcon(Icon emptyIcon) { this.emptyIcon = emptyIcon; } /** Returns the text used for this button when a dockable is stored*/ public String getFullText() { return fullText; } /** Returns the text used for this button when a dockable is stored*/ public void setFullText(String fullText) { this.fullText = fullText; } /** Returns the text used for as tooltip this button when a dockable is stored*/ public String getFullTooltip() { return fullTooltip; } /** Updates the text used as tooltip for this button when no dockable is stored. * The special value '&1' will be replaced by the name of this dockable. *

* For example "&1 stored" could be replaced by "MyDockable stored" */ public void setFullTooltip(String fullTooltip) { this.fullTooltip = fullTooltip; } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/DockingBorderLayout.java0000644000175000017500000002503110573516350027014 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking; import java.util.Hashtable; import java.awt.*; import javax.swing.*; /** A layout adapted to autohide panels. *

* This layout is like a BorderLayout but corners are always empty * (for example, the TOP component starts with an x coordinate equal to the * width of the LEFT component). * * @author Lilian Chamontin, vlsolutions. * @version 1.0 */ public class DockingBorderLayout implements LayoutManager2{ Component topComp, leftComp, bottomComp, rightComp, centerComp; public DockingBorderLayout() { } public float getLayoutAlignmentX(Container target) { return 0.5F; } public float getLayoutAlignmentY(Container target) { return 0.5F; } public void invalidateLayout(Container target) { } public Dimension maximumLayoutSize(Container target) { return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); } public void addLayoutComponent(Component comp, Object constraints) { addLayoutComponent((String)constraints, comp); } public void removeLayoutComponent(Component comp) { } public void addLayoutComponent(String name, Component comp) { if (name.equals(BorderLayout.NORTH)){ topComp = comp; } else if (name.equals(BorderLayout.EAST)){ rightComp = comp; } else if (name.equals(BorderLayout.SOUTH)){ bottomComp = comp; } else if (name.equals(BorderLayout.WEST)){ leftComp = comp; } else if (name.equals(BorderLayout.CENTER)){ centerComp = comp; } else { throw new IllegalArgumentException("wrong constraint"); } } public Dimension minimumLayoutSize(Container parent) { synchronized (parent.getTreeLock()) { Dimension dim = new Dimension(0, 0); if (leftComp != null && leftComp.isVisible()) { Dimension d = leftComp.getMinimumSize(); dim.width += d.width; dim.height = Math.max(d.height, dim.height); } if (rightComp != null && rightComp.isVisible()) { Dimension d = rightComp.getMinimumSize(); dim.width += d.width; dim.height = Math.max(d.height, dim.height); } if (centerComp != null && centerComp.isVisible()) { Dimension d = centerComp.getMinimumSize(); dim.width += d.width; dim.height = Math.max(d.height, dim.height); } if (topComp != null && topComp.isVisible()) { Dimension d = topComp.getMinimumSize(); dim.width = Math.max(d.width, dim.width); dim.height += d.height; } if (bottomComp != null && bottomComp.isVisible()) { Dimension d = bottomComp.getMinimumSize(); dim.width = Math.max(d.width, dim.width); dim.height += d.height; } Insets insets = parent.getInsets(); dim.width += insets.left + insets.right; dim.height += insets.top + insets.bottom; return dim; } } public Dimension preferredLayoutSize(Container parent) { synchronized (parent.getTreeLock()) { Dimension dim = new Dimension(0, 0); if (leftComp != null && leftComp.isVisible()) { Dimension d = leftComp.getPreferredSize(); dim.width += d.width; dim.height = Math.max(d.height, dim.height); } if (rightComp != null && rightComp.isVisible()) { Dimension d = rightComp.getPreferredSize(); dim.width += d.width; dim.height = Math.max(d.height, dim.height); } if (centerComp != null && centerComp.isVisible()) { Dimension d = centerComp.getPreferredSize(); dim.width += d.width; dim.height = Math.max(d.height, dim.height); } if (topComp != null && topComp.isVisible()) { Dimension d = topComp.getPreferredSize(); dim.width = Math.max(d.width, dim.width); dim.height += d.height; } if (bottomComp != null && bottomComp.isVisible()) { Dimension d = bottomComp.getPreferredSize(); dim.width = Math.max(d.width, dim.width); dim.height += d.height; } Insets insets = parent.getInsets(); dim.width += insets.left + insets.right; dim.height += insets.top + insets.bottom; return dim; } } private int getSideWidth(Component comp){ if (comp == null) return 0; if (comp.isVisible()) return comp.getPreferredSize().width; return 0; } private int getSideHeight(Component comp){ if (comp == null) return 0; if (comp.isVisible()) return comp.getPreferredSize().height; return 0; } /** overridden to adjust position (x(top) = width(left), y(left) = height(top) */ public void layoutContainer(Container target) { synchronized (target.getTreeLock()) { Insets insets = target.getInsets(); int top = insets.top; int bottom = target.getHeight() - insets.bottom; int left = insets.left; int right = target.getWidth() - insets.right; int lw = getSideWidth(leftComp); int rw = getSideWidth(rightComp); int th = getSideHeight(topComp); int bh = getSideHeight(bottomComp); if (topComp != null && topComp.isVisible()) { topComp.setSize(right - left - lw - rw, topComp.getHeight()); Dimension d = topComp.getPreferredSize(); topComp.setBounds(left + lw, top, right - left - lw - rw, d.height); } if (bottomComp != null && bottomComp.isVisible()) { bottomComp.setSize(right - left - lw - rw, bottomComp.getHeight()); Dimension d = bottomComp.getPreferredSize(); bottomComp.setBounds(left + lw, bottom - d.height, right - left - lw - rw , d.height); } if (rightComp != null && rightComp.isVisible()) { rightComp.setSize(rightComp.getWidth(), bottom - top - th - bh); Dimension d = rightComp.getPreferredSize(); rightComp.setBounds(right - d.width, top + th, d.width, bottom - top - th - bh); } if (leftComp != null && leftComp.isVisible()) { leftComp.setSize(leftComp.getWidth(), bottom - top); Dimension d = leftComp.getPreferredSize(); leftComp.setBounds(left, top + th, d.width, bottom - top - th - bh); } if (centerComp != null && centerComp.isVisible()) { centerComp.setBounds(left + lw, top + th, right - left-lw - rw, bottom - top - th - bh); } } } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/DockingConstants.java0000644000175000017500000001545410573516350026365 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking; /** Constants used by the DockingDesktop to position Dockables. *

* API Users will use these constants to interact with the DockingDesktop. *

* These constants are defined as enumerations of Hide and Split classes, in order * to avoid runtime errors. * * @author Lilian Chamontin, vlsolutions. * @version 1.0 */ public class DockingConstants { public static final int INT_SPLIT_TOP = 0; public static final int INT_SPLIT_LEFT = 1; public static final int INT_SPLIT_BOTTOM = 2; public static final int INT_SPLIT_RIGHT = 3; /** A constant describing a VERTICAL splitting operation where the new component * goes on the TOP part */ public static final Split SPLIT_TOP = new Split(INT_SPLIT_TOP); /** A constant describing an HORIZONTAL splitting operation where the new component * goes on the LEFT part */ public static final Split SPLIT_LEFT = new Split(INT_SPLIT_LEFT); /** A constant describing a VERTICAL splitting operation where the new component * goes on the BOTTOM part */ public static final Split SPLIT_BOTTOM = new Split(INT_SPLIT_BOTTOM); /** A constant describing an HORIZONTAL splitting operation where the new component * goes on the RIGHT part */ public static final Split SPLIT_RIGHT = new Split(INT_SPLIT_RIGHT); public static final int INT_HIDE_TOP = 0; public static final int INT_HIDE_LEFT = 1; public static final int INT_HIDE_BOTTOM = 2; public static final int INT_HIDE_RIGHT = 3; /** A constant describing an auto-hide operation where the component * goes on the TOP border */ public static final Hide HIDE_TOP = new Hide(INT_HIDE_TOP); /** A constant describing an auto-hide operation where the component * goes on the LEFT border */ public static final Hide HIDE_LEFT = new Hide(INT_HIDE_LEFT); /** A constant describing an auto-hide operation where the component * goes on the BOTTOM border */ public static final Hide HIDE_BOTTOM = new Hide(INT_HIDE_BOTTOM); /** A constant describing an auto-hide operation where the component * goes on the RIGHT border */ public static final Hide HIDE_RIGHT = new Hide(INT_HIDE_RIGHT); /** Typesafe enumeration describing a split operation on the DockingDesktop.*/ public static class Split { private int value; private Split(int value){ this.value = value; } public int value(){ return value; } } /** Typesafe enumeration describing an auto-hide operation on the DockingDesktop.*/ public static class Hide { private int value; private Hide(int value){ this.value = value; } public int value(){ return value; } } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/DockingContext.java0000644000175000017500000005444310573516350026036 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking; import com.vlsolutions.swing.docking.event.DockableSelectionEvent; import com.vlsolutions.swing.docking.event.DockableSelectionListener; import com.vlsolutions.swing.docking.event.DockableStateChangeEvent; import com.vlsolutions.swing.docking.event.DockableStateChangeListener; import com.vlsolutions.swing.docking.event.DockableStateWillChangeEvent; import com.vlsolutions.swing.docking.event.DockableStateWillChangeListener; import com.vlsolutions.swing.docking.event.DockingActionEvent; import com.vlsolutions.swing.docking.event.DockingActionListener; import java.awt.Container; import java.awt.KeyboardFocusManager; import java.awt.Window; import java.awt.event.WindowEvent; import java.beans.PropertyChangeEvent; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.WeakHashMap; import javax.swing.SwingConstants; import javax.swing.SwingUtilities; import javax.swing.event.AncestorEvent; import javax.swing.event.AncestorListener; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; /** A context that can be shared by multiple docking desktops. *

* Keeps track of registered dockables and manages import export. *

* A DockingContext can be seen as the top-most grouping element of docking * (as DockingDesktop can be contained is a context), and as such, all * methods related to workspace management have been promoted to this class. * * * @author Lilian Chamontin, VLSolutions * @since 2.1 * @update 2007/01/08 Lilian Chamontin : updated registerDockable to * put the dockable in the CLOSED state if not previously registered (was null before v2.1.3) */ public class DockingContext { /** All dockables must be registered (even if not shown) in order to be processed * by the XML Parser or to be displayed in the DockingSelectorDialog */ protected ArrayList registeredDockables = new ArrayList(); /** inner state of the dockables */ protected HashMap dockableStates = new HashMap(); // key : Dockable / value : /* DockableState change listeners */ // before state change : private ArrayList dockableStateWillChangeListeners = new ArrayList(); // after state change : private ArrayList dockableStateChangeListeners = new ArrayList(); /** selection change */ private ArrayList dockableSelectionListeners = new ArrayList(); /** Docking action listener (preferred way to track docking changes) */ private ArrayList dockingActionListeners = new ArrayList(); private ArrayList desktops = new ArrayList(); /** An always ordered list of window (used to keep track of which one is above which one, to resolve some * DnD issues) */ private LinkedList ownedWindowActivationOrder = new LinkedList(); /** Finds new Dockables given a key name (useful when processing an XML stream if the dockable * hasn't been registered yet. */ private DockableResolver dockableResolver = null; /** Constructs a new DockingContext */ public DockingContext() { } /** Adds a desktop to this context */ public void addDesktop(DockingDesktop desktop){ if (! desktops.contains((desktop))){ desktops.add(desktop); } } /** Removes a desktop from this context */ public void removeDesktop(DockingDesktop desktop){ desktops.remove(desktop); // time to check if some windows should be removed as not ancestors of remaining desktops Iterator it = ownedWindowActivationOrder.iterator(); while (it.hasNext()){ Window w = (Window) it.next(); boolean ancestor = false; for (int i=0; i < desktops.size(); i++){ DockingDesktop desk = (DockingDesktop) desktops.get(i); if (w.isAncestorOf(desk)){ ancestor = true; break; } } if (! ancestor){ // this window isn't an ancestor of any managed desktops : we drop it it.remove(); } } } /** Every dockable must be registered in order to be managed by a DockingDesktop. *

* if this method is invoked and the dockable is already registered, nothing happens. * if the dockable is still unknown, it is added to the dockables set and (since 2.1.3) * its state is set to CLOSED (prior 2.1.3, the state was null). * * */ public void registerDockable(Dockable dockable){ if (! registeredDockables.contains(dockable)){ registeredDockables.add(dockable); } if (getDockableState(dockable) == null){ // should be always the case here // 2007/01/08 setDockableState(dockable, new DockableState(null, dockable, DockableState.STATE_CLOSED)); } } /** Unregisters the dockable, which can be garbage collected (no longer used * by docking desktops. * */ public void unregisterDockable(Dockable dockable){ close(dockable); // in case it was still visible registeredDockables.remove(dockable); dockableStates.remove(dockable); // 2005/11/09 } /** Close this dockable */ public void close(Dockable dockable){ DockableState state = (DockableState) dockableStates.get(dockable); DockingDesktop desk = state.getDesktop(); if (desk != null){ desk.close(dockable); } } /** Returns the current state of a dockable (CLOSED, HIDDEN, DOCKED, MAXIMIZED, FLOATING) */ public DockableState getDockableState(Dockable dockable){ return (DockableState) dockableStates.get(dockable); } /** Updates the current state of a dockable */ public void setDockableState(Dockable dockable, DockableState state){ dockableStates.put(dockable, state); } /** Adds a new DockableStateChangeListener to this desktop. *

* DockableStateChange Events are triggered after the state change. * *

As of version 2.0 of the framework, this method can also be replaced by * adding a propertychangeListener on the DockKey object (and react to its DockableState * property). * * */ public void addDockableStateChangeListener(DockableStateChangeListener listener){ if (!dockableStateChangeListeners.contains(listener)){ dockableStateChangeListeners.add(listener); } } /** Removes a DockableStateChangeListener from this desktop. * */ public void removeDockableStateChangeListener(DockableStateChangeListener listener){ dockableStateChangeListeners.remove(listener); } /** Adds a new DockableStateWillChangeListener to this desktop. *

* DockableStateWillChange Events are triggered before the state change, and * are vetoable. * */ public void addDockableStateWillChangeListener(DockableStateWillChangeListener listener){ if (!dockableStateWillChangeListeners.contains(listener)){ dockableStateWillChangeListeners.add(listener); } } /** Removes a DockableStateWillChangeListener from this desktop. * */ public void removeDockableStateWillChangeListener(DockableStateWillChangeListener listener){ dockableStateWillChangeListeners.remove(listener); } /** Creates and returns an array of all registered dockable with their current * state. *

* Visibility states are [DockableState.STATE_CLOSED, STATE_DOCKED, STATE_HIDDEN] * @return an array of DockableState */ public DockableState[] getDockables(){ DockableState [] states = new DockableState[registeredDockables.size()]; for (int i = 0; i < states.length; i++) { Dockable d = (Dockable) registeredDockables.get(i); states[i] = (DockableState) dockableStates.get(d); if (states[i] == null){ DockableState closed = new DockableState(null, d, DockableState.STATE_CLOSED); states[i] = closed; } } return states; } /** Saves the current desktop configuration into an XML stream. *

* The workspace is composed of every desktop layouts associated * with this context (desktops are identified by their 'desktopName' property). * *

* The stream is not closed at the end of the operation. * * @see #readXML(InputStream) * */ public void writeXML(OutputStream stream) throws IOException { PrintWriter out = new PrintWriter(stream); out.println(""); out.println(""); for (int i=0; i < desktops.size(); i++){ DockingDesktop desktop = (DockingDesktop) desktops.get(i); desktop.writeDesktopNode(out); } out.println(""); out.flush(); } /** Reads an XML encoded stream as the new desktop configuration. *

* When the method returns, the desktops associated to this context are totally * reconfigured with posiibly different dockables at different positions. *

* Note : The DockKeys of the stream must be registered with * the {@link #registerDockable(Dockable) registerDockable} method, * prior readXML.
* * This is the case if the desktop is already open and dockables * laid out, but might not be the case if this method is used at application startup * to populate an empty desktop. *

* Note : altenatively (since 2.1.2) if a DockableResolver has been set, it will * be use to auto-register the new dockables encountered along the stream.
*

* Dismisses all visible dockables (docked and auto-hidden), and clear their DockableState. *

* The stream is not closed at the end of the operation. *

* Note : When multiple desktops are loaded from the stream, the context uses their "desktopName" * property (desk.getDesktopName()) to identify them. * * @see #writeXML(OutputStream) * @see #registerDockable(Dockable) * @see #setDockableResolver(DockableResolver) * */ public void readXML(InputStream in) throws ParserConfigurationException, IOException, SAXException { // remove all dockable states for (int i=0; i < desktops.size(); i++){ DockingDesktop desk = (DockingDesktop) desktops.get(i); desk.clear(); } dockableStates.clear(); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document doc = builder.parse(in); Element root = doc.getDocumentElement(); if (root.getNodeName().equals("DockingDesktop")){ // this is an old desktop file, missing the VLDocking root node (VLDocking 2.0 format) // so we noly have a single desktop DockingDesktop desk = getDesktopByName(null); // only one desk.readDesktopNode(root); } else { NodeList desktopChildren = root.getChildNodes(); for (int i = 0, len = desktopChildren.getLength(); i < len; i++) { Node node = desktopChildren.item(i); if (node instanceof Element){ Element deskChild = (Element) node; DockingDesktop desk = getDesktopByName(deskChild.getAttribute("name")); desk.readDesktopNode(deskChild); } } } } private DockingDesktop getDesktopByName(String name){ if (desktops.size() == 1){ // always found if only one desktop DockingDesktop desktop = (DockingDesktop) desktops.get(0); return desktop; } for (int i=0; i < desktops.size(); i++){ DockingDesktop desktop = (DockingDesktop) desktops.get(i); if (desktop.getDesktopName().equals(name)){ return desktop; } } throw new RuntimeException("No desktop found with name : " + name); } /** constructs and returns the list of dockables corresponding to a desktop, at a specific state*/ public ArrayList getDockablesByState(DockingDesktop desktop, int state) { ArrayList list = new ArrayList(); for (int i=0; i < registeredDockables.size(); i++){ Dockable d = (Dockable) registeredDockables.get(i); DockableState dState = (DockableState)dockableStates.get(d); if (dState != null && dState.getDesktop() == desktop && dState.getState() == state){ list.add(d); } } return list; } /** Returns the (registered) dockable corresponding to the given key id, * or null if not found *

* Note : since VLDocking 2.1.2, this method also tries to use its DockableResolver * if null would have been returned. * @see DockableResolver */ public Dockable getDockableByKey(String dockKey){ for (int i = 0; i < registeredDockables.size(); i++) { Dockable d = (Dockable)registeredDockables.get(i); if (d.getDockKey().getKey().equals(dockKey)){ return d; } } // not found if (dockableResolver != null){ Dockable d = dockableResolver.resolveDockable(dockKey); if (d != null){ registerDockable(d); // a new one } return d; // might be null } return null; } /*package protected */ void fireDockableStateChange(DockableStateChangeEvent e){ for (int i = 0; i < dockableStateChangeListeners.size(); i++) { DockableStateChangeListener listener = (DockableStateChangeListener) dockableStateChangeListeners.get(i); listener.dockableStateChanged(e); } } /*package protected */ boolean fireDockableStateWillChange(DockableStateWillChangeEvent e){ DockingDesktop desk = e.getFutureState().getDesktop(); if (desk.getMaximizedDockable() != null){ // veto events coming from autohide and floating components if a component is maximized // @todo : this could be improved by disabling the dock and attach properties of // the remaining visible dockables to avoid having the user don't understand // why a button doesn't react. if (desk.getMaximizedDockable() != e.getCurrentState().getDockable()){ if (e.getFutureState().isDocked()){ if (e.getCurrentState().isHidden()){ return false; // refused } else if (e.getCurrentState().isFloating()){ return false; } } } } // dispatch events and listen to vetoes for (int i = 0; i < dockableStateWillChangeListeners.size(); i++) { DockableStateWillChangeListener listener = ( DockableStateWillChangeListener) dockableStateWillChangeListeners.get(i); listener.dockableStateWillChange(e); if (!e.isAccepted()){ // stop as soon as the operation is cancelled return false; } } return true; } /** Adds a new DockableSelectionListener to this desktop. *

* DockableSelection Events are triggered when a dockable takes the focus. * */ public void addDockableSelectionListener(DockableSelectionListener listener){ if (!dockableSelectionListeners.contains(listener)){ dockableSelectionListeners.add(listener); } } /** Removes a DockableSelectionListener from this desktop. * */ public void removeDockableSelectionListener(DockableSelectionListener listener){ dockableSelectionListeners.remove(listener); } /*package protected */ void fireDockableSelectionChange(DockableSelectionEvent e){ for (int i = 0; i < dockableSelectionListeners.size(); i++) { DockableSelectionListener listener = (DockableSelectionListener) dockableSelectionListeners.get(i); listener.selectionChanged(e); } } public void addDockingActionListener(DockingActionListener listener) { if (!dockingActionListeners.contains(listener)){ dockingActionListeners.add(listener); } } public void removeDockingActionListener(DockingActionListener listener) { dockingActionListeners.remove(listener); } /** returns false if the docking action is rejected, or true if accepted by all listeners*/ boolean fireAcceptDockingAction(DockingActionEvent e){ /*package protected */ for (int i = 0; i < dockingActionListeners.size(); i++) { DockingActionListener listener = (DockingActionListener) dockingActionListeners.get(i); if (!listener.acceptDockingAction(e)){ return false; } } return true; } /*package protected */ void fireDockingActionPerformed(DockingActionEvent e){ for (int i = 0; i < dockingActionListeners.size(); i++) { DockingActionListener listener = (DockingActionListener) dockingActionListeners.get(i); listener.dockingActionPerformed(e); } } /** Returns a list of the desktops sharing this context */ public ArrayList getDesktopList() { return desktops; } /** used to track window activation (to have an up to date z ordered list of window) */ void windowActivated(WindowEvent e){ /* package protected */ /* these events are forwarded by docking desktops */ Window w = e.getWindow(); if (ownedWindowActivationOrder.size()>0 && ownedWindowActivationOrder.getFirst() != w){ ownedWindowActivationOrder.remove(w); ownedWindowActivationOrder.addFirst(w); } } /** Returns a list of owned windows, ordered by window z-order */ LinkedList getOwnedWindowActionOrder(){ /* package protected */ return ownedWindowActivationOrder; } /** Registers a new window */ void registerWindow(Window w) { /* package protected */ ownedWindowActivationOrder.addLast(w); } /** Returns the dockable resolver used by this context (or null if none defined) * @since 2.1.2 */ public DockableResolver getDockableResolver() { return dockableResolver; } /** Updates the dockable resolver used by this context (can be set to null) * @since 2.1.2 */ public void setDockableResolver(DockableResolver dockableResolver) { this.dockableResolver = dockableResolver; } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/DockingDesktop.java0000644000175000017500000045737010573516350026031 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking; import java.beans.*; import java.io.*; import java.util.*; import javax.xml.parsers.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; import org.w3c.dom.*; import org.xml.sax.*; import com.vlsolutions.swing.docking.event.*; import com.vlsolutions.swing.docking.ui.DockingUISettings; import javax.swing.event.AncestorEvent; import javax.swing.event.AncestorListener; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; /** * The DockingDesktop is the main class of the VLDocking Framework. *

It is the equivalent of what is JDesktopPane for JInternalWindow : * a JLayeredPane customized to include : *

* * @author Lilian Chamontin, VLSolutions. * @version 2.0 * * @update 2005/10/06 Lilian Chamontin : added support for dnd to floatables * @update 2005/10/07 Lilian Chamontin : cancel drag operation with ESCAPE key * @update 2005/11/08 Lilian Chamontin : added support for global width/height drop (in split method) * @update 2005/11/14 Lilian Chamontin : reworked setFloating methods. * @update 2005/12/08 Lilian Chamontin : fixed a bug related to multiple desktop usage (when moving a window after * the desktop has been removed from hierarchy, the listeners were still invoked and caused a NPE in moveFloatingWindows). * * @update 2006/12/01 Lilian Chamontin : fixed a NPE when closing a window with some floating children remaining * @update 2006/12/19 Lilian Chamontin : fixed a memory leak issue due to keyboard focus manager handling */ public class DockingDesktop extends JLayeredPane { private static final String CURRENT_VERSION_NUMBER = "2.1.4"; private static final String BUILD_DATE = "2007/03/07"; static { // install UI settings if not already done DockingUISettings.getInstance().installUI(); } /** contextual data that can be shared by multiple desktops */ private DockingContext context; /** panel containing autohidepanels on borders and dockingpanel at center */ private JPanel contentPane = new JPanel(new DockingBorderLayout()); /** main central container for dockables */ protected DockingPanel dockingPanel = new DockingPanel(); /** container responsible for auto-hidden components expansion */ protected AutoHideExpandPanel expandPanel = createAutoHideExpandPanel(); /** panel used to display autohide buttons */ protected AutoHideButtonPanel topBorderPane= new AutoHideButtonPanel(expandPanel, DockingConstants.INT_HIDE_TOP); /** panel used to display autohide buttons */ protected AutoHideButtonPanel leftBorderPane = new AutoHideButtonPanel(expandPanel, DockingConstants.INT_HIDE_LEFT); /** panel used to display autohide buttons */ protected AutoHideButtonPanel bottomBorderPane = new AutoHideButtonPanel(expandPanel, DockingConstants.INT_HIDE_BOTTOM); /** panel used to display autohide buttons */ protected AutoHideButtonPanel rightBorderPane = new AutoHideButtonPanel(expandPanel, DockingConstants.INT_HIDE_RIGHT); /** array containing the border panes */ protected AutoHideButtonPanel[] borderPanes = {topBorderPane, leftBorderPane, bottomBorderPane, rightBorderPane}; private HashMap autoHideButtons = new HashMap(); // key : DockKey / value : AutoHideButton private DragControler dragControler; /** a component used to track position of the current maximized component */ private MaximizedComponentReplacer dummyMaximedReplacer = new MaximizedComponentReplacer();// 2007/01/18 //new JLabel(); /** the current maximized component */ private Component maximizedComponent; /** a flag set when adding a maximized component : true is this one is heavyweight * Only used with heavyweight support AND singleHeavyWeightComponent */ private boolean currentMaximizedComponentIsHeavyWeight = false; private JComponent mouseMotionGrabber = new JComponent() { // component used to grab mouse events under the expansion panel // only visible (and active) when expansion panel is visible }; /** this timer is only used when the java version is < 1.5 (version>=1.5 uses the MouseInfo component)*/ private javax.swing.Timer mouseOutOfExpandedPanelTimer = new javax.swing.Timer(1000, new ActionListener() { // timer used to hide the expanded panel when mouse is out too long public void actionPerformed(ActionEvent actionEvent) { if (!expandPanel.isActive() && expandPanel.shouldCollapse()) { // do not hide it if it has got the focus // or if a non-collapsible operation is occuring expandPanel.collapse(); } } }); /** groups of tabs (used to re-tab autohidden dockable)*/ protected HashMap tabbedGroups = new HashMap(); // / private FocusHandler focusHandler = new FocusHandler(); /** return state for floating dockables */ protected HashMap previousFloatingDockableStates = new HashMap(); // key dockable / value dockable state /** Unique name for this desktop : used since 2.1 to support multiple desktops*/ private String desktopName; // 2005/10/10 added support for moving the floating dialogs with the frame private Point lastWindowLocation = null; private ComponentAdapter windowMovementListener = new ComponentAdapter(){ public void componentMoved(ComponentEvent e){ moveFloatingWindows(); } }; WindowListener windowListener = new WindowAdapter() { public void windowActivated(WindowEvent e) { context.windowActivated(e); //foward activation events to the context } }; /** Action used for keyboard binding : closes the current dockable */ private AbstractAction closeAction = new AbstractAction(){ public void actionPerformed(ActionEvent e){ Dockable d = focusHandler.getCurrentDockable(); if (d != null){ if (d.getDockKey().isCloseEnabled()){ int state = d.getDockKey().getDockableState(); if (state == DockableState.STATE_DOCKED || state == DockableState.STATE_FLOATING || state == DockableState.STATE_HIDDEN){ close(d); } } } } }; /** Action used for keyboard binding : maximize/restore the current dockable */ private AbstractAction maximizeAction = new AbstractAction(){ public void actionPerformed(ActionEvent e){ Dockable d = focusHandler.getCurrentDockable(); if (d != null){ if (d.getDockKey().isMaximizeEnabled()){ int state = d.getDockKey().getDockableState(); if (state == DockableState.STATE_DOCKED){ maximize(d); } else if (state == DockableState.STATE_MAXIMIZED){ restore(d); } } } } }; /** Action used for keyboard binding : autohide/dock the current dockable */ private AbstractAction dockAction = new AbstractAction(){ public void actionPerformed(ActionEvent e){ Dockable d = focusHandler.getCurrentDockable(); if (d != null){ if (d.getDockKey().isAutoHideEnabled()){ int state = d.getDockKey().getDockableState(); if (state == DockableState.STATE_DOCKED){ setAutoHide(d, true); } else if (state == DockableState.STATE_HIDDEN){ setAutoHide(d, false); } } } } }; /** Action used for keyboard binding : float/attach the current dockable */ private AbstractAction floatAction = new AbstractAction(){ public void actionPerformed(ActionEvent e){ Dockable d = focusHandler.getCurrentDockable(); if (d != null){ if (d.getDockKey().isFloatEnabled()){ int state = d.getDockKey().getDockableState(); if (state == DockableState.STATE_DOCKED){ setFloating(d, true); } else if (state == DockableState.STATE_FLOATING){ setFloating(d, false); } } } } }; /** Action used for keyboard binding : cancel the current operation */ private AbstractAction cancelAction = new AbstractAction(){ public void actionPerformed(ActionEvent e){ dragControler.cancelDrag(); } }; /** Constructs a DockingDesktop with a default name (suitable for single-desktop applications). */ public DockingDesktop() { this("", null); } /** Constructs a DockingDesktop with a given name (suitable for multiple-desktop applications). *

* This also constructs a new Docking Context, that can be shared with other Desktops. */ public DockingDesktop(String desktopName) { this(desktopName, null); } /** Constructs a DockingDesktop with a given name (suitable for multiple-desktop applications). */ public DockingDesktop(String desktopName, DockingContext context) { setDesktopName(desktopName); if (context == null){ this.context = new DockingContext(); // initial (single desktop) context } else { this.context = context; // shared context issued from another dekstop } this.context.addDesktop(this); this.dragControler = new DragControler(this); // // add(contentPane, BorderLayout.CENTER); topBorderPane.setVisible(false); leftBorderPane.setVisible(false); bottomBorderPane.setVisible(false); rightBorderPane.setVisible(false); contentPane.add(topBorderPane, BorderLayout.NORTH); contentPane.add(leftBorderPane, BorderLayout.WEST); contentPane.add(bottomBorderPane, BorderLayout.SOUTH); contentPane.add(rightBorderPane, BorderLayout.EAST); contentPane.add(dockingPanel, BorderLayout.CENTER); add(contentPane, DEFAULT_LAYER); mouseMotionGrabber.setVisible(false); mouseMotionGrabber.addMouseListener(new MouseAdapter() { boolean canUseMouseInfo = DockingUtilities.canUseMouseInfo(); public void mouseEntered(MouseEvent e) { // means that the mouse is not above the expanded panel if (! canUseMouseInfo){ // only for 1.4 codebase or untrusted envs mouseOutOfExpandedPanelTimer.restart(); //2005/11/01 } } public void mouseExited(MouseEvent e) { // means that the mouse is probably above the expanded panel (or out of the window) if (! canUseMouseInfo){ // only for 1.4 codebase or untrusted envs mouseOutOfExpandedPanelTimer.stop(); //2005/11/01 } } public void mousePressed(MouseEvent e) { // collapse the expanded panel and redispatch the event to the underlying frame // for processing by the real component clicked by the user expandPanel.collapse(); Window w = SwingUtilities.getWindowAncestor(DockingDesktop.this); if (w != null) { w.dispatchEvent(e); } } }); expandPanel.installDocking(this); expandPanel.setVisible(false); add(mouseMotionGrabber, new Integer(MODAL_LAYER.intValue() - 1)); add(expandPanel, MODAL_LAYER); ComponentListener resizeListener = new ComponentAdapter() { /* resize listener is added to the desktop and to the contentPane */ public void componentResized(ComponentEvent event) { int w = getWidth(); int h = getHeight(); Insets i = getDockingPanelInsets(); if (event.getComponent() == DockingDesktop.this){ // hide the expanded panel if necessary expandPanel.collapse(); // resize the panel contentPane.setBounds(0, 0, w, h); revalidate(); } else if (event.getComponent() == dockingPanel){ if (maximizedComponent != null) { if (DockingPreferences.isLightWeightUsageEnabled()){ maximizedComponent.setBounds(i.left, i.top, w - i.left - i.right, h - i.top - i.bottom); } else { if (DockingPreferences.isSingleHeavyWeightComponent()){ if (DockingUtilities.isHeavyWeightComponent(maximizedComponent)){ maximizedComponent.setBounds(i.left, i.top, w - i.left - i.right, h - i.top - i.bottom); } else { maximizedComponent.getParent().setBounds(i.left, i.top, w - i.left - i.right, h - i.top - i.bottom); } } else { maximizedComponent.getParent().setBounds(i.left, i.top, w - i.left - i.right, h - i.top - i.bottom); } } } mouseMotionGrabber.setBounds(i.left, i.top, w - i.left - i.right, h - i.top - i.bottom); dockingPanel.revalidate(); } } }; addComponentListener(resizeListener); dockingPanel.addComponentListener(resizeListener); expandPanel.addPropertyChangeListener(AutoHideExpandPanel.PROPERTY_EXPANDED, new PropertyChangeListener(){ public void propertyChange(PropertyChangeEvent e) { if (e.getNewValue().equals(Boolean.TRUE)){ mouseMotionGrabber.setVisible(true); } else { mouseMotionGrabber.setVisible(false); } } }); mouseOutOfExpandedPanelTimer.setRepeats(false); // avoid loops /*KeyboardFocusManager.getCurrentKeyboardFocusManager().addPropertyChangeListener( "focusOwner", focusHandler); //2006/08/21 : back to life (was in comments in 2.1.0)*/ installKeyboardBindings(); // optional window following final boolean floatingContainerFollowParentWindow = UIManager.getBoolean("FloatingContainer.followParentWindow"); addAncestorListener(new AncestorListener(){ public void ancestorAdded(AncestorEvent event) { KeyboardFocusManager.getCurrentKeyboardFocusManager().addPropertyChangeListener( "focusOwner", focusHandler); //2006/08/21 : back to life (was in comments in 2.1.0) // 2006/12/19 now integrated to ancestor hierarchy to avoid gc leaks Window w = SwingUtilities.getWindowAncestor(DockingDesktop.this); w.addWindowListener(windowListener); DockingDesktop.this.context.registerWindow(w); // first activation required to register the window if (floatingContainerFollowParentWindow){ w.addComponentListener(windowMovementListener); } } public void ancestorRemoved(AncestorEvent event){// 2005/12/08 KeyboardFocusManager.getCurrentKeyboardFocusManager().removePropertyChangeListener( "focusOwner", focusHandler); //2006/12/19 if (event == null || event.getAncestorParent() == null){ // 2006/12/01 protection againts NPE return; } else { Window w = SwingUtilities.getWindowAncestor(event.getAncestorParent()); if (w !=null){ // 2007/03/07 hope it helps with desktops on JDialogs w.removeWindowListener(windowListener); if (floatingContainerFollowParentWindow){ w.removeComponentListener(windowMovementListener); } } } } public void ancestorMoved(AncestorEvent event){ } }); } /** Registers listeners for notable keyboard events (CLOSE, DOCK/HIDE, MAXIMIZE/RESTORE, float/attach). * KeyStroke bindings can be defined and overriden this UIManager properties (see DockingUISettings for * details). * */ private void installKeyboardBindings(){ KeyStroke ks = (KeyStroke) UIManager.get("DockingDesktop.closeActionAccelerator"); if (ks != null){ getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(ks, "close"); getActionMap().put("close", closeAction); } ks = (KeyStroke) UIManager.get("DockingDesktop.maximizeActionAccelerator"); if (ks != null){ getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(ks, "maximize"); getActionMap().put("maximize", maximizeAction); } ks = (KeyStroke) UIManager.get("DockingDesktop.dockActionAccelerator"); if (ks != null){ getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(ks, "dock"); getActionMap().put("dock", dockAction); } ks = (KeyStroke) UIManager.get("DockingDesktop.floatActionAccelerator"); if (ks != null){ getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(ks, "float"); getActionMap().put("float", floatAction); } ks = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0); // general cancel action 2005/10/07 getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(ks, "cancel"); getActionMap().put("cancel", cancelAction); } /** Returns the currently selected dockable, or null if none is selected. *

* A selected dockable is a dockable whose component contains the keyboard focus. */ public Dockable getSelectedDockable(){ return focusHandler.currentDockable; } /** Set the desktop contents to be opaque or transparent. *

* Transparent contents allow adding background images/information when no dockable is visible (everything closed * or autohidden). *

* Default value is true (opaque). * * @since 2.0.4 */ public void setOpaqueContents(boolean opaque){ contentPane.setOpaque(opaque); dockingPanel.setOpaque(opaque); } /** Returns whether this desktop's contents are opaque or not. *

* Default value is true (opaque). * * @see #setOpaqueContents(boolean). * @since 2.0.4 */ public boolean isOpaqueContents(){ return contentPane.isOpaque(); } /** Returns the docking panel used by this desktop */ DockingPanel getDockingPanel(){ /* package protected method */ return dockingPanel; } /** Every dockable must be registered in order to be shown in the DockingDesktop. * *

Registration is automatic for shown dockables : * methods setCentralDockable(), split(), createTab(), hide()... leading to have the dockable * visible call registerDockable() ) *

for not shown dockable (in order to read a configuration from an XML stream, or to list * the dockable in DockingSelectorDialog ), this method must be called manually. *

* As of version 2.1, this method call is forwarded to the DockingContext * */ public void registerDockable(Dockable dockable){ context.registerDockable(dockable); } /** Unregisters the dockable, which can be garbage collected (no longer used * by the docking desktop. *

* As of version 2.1, this method call is forwarded to the DockingContext * */ public void unregisterDockable(Dockable dockable){ //context.registerDockable(dockable); // 2006/09/06 context.unregisterDockable(dockable); // 2006/09/06 } /** Returns a String containing the version of the docking framework in the format M.m.r * where M is the major , m the minor and r the release. *@since 2.0 */ public static String getDockingFrameworkVersion(){ return CURRENT_VERSION_NUMBER; } /** Returns a String containing the release date of the current version. *@since 2.0 */ public static String getDockingFrameworkBuildDate(){ return BUILD_DATE; } /** Adds a view in a tab, or create it if it doesn't exist. * * @param base the reference dockable * @param dockable a dockable to add at the same position than base. * if base is not already child of a tabbedpane, a new tabbedpane will be created and inserted * at base's location. * @param order the tab order of view in its tabbed pane. * */ public void createTab(Dockable base, Dockable dockable, int order){ createTab(base, dockable, order, false); } /** Add a view in a tab, or create it if it doesn't exist. *

Optional added tab selection. * * @param base an existing dockable, either displayed in a DockableContainer or * in a TabbedDockableContainer. *

If base is displayed by a DockableContainer, this container will be replaced * by a TabbedDockableContainer. * @param dockable the dockable to add * @param order the tab order of view in its tabbed pane. * @param select if true, will select the added tab (make it appear at front) * */ public void createTab(Dockable base, Dockable dockable, int order, boolean select){ createTab(base, dockable, order, select, true); } /** private implementation wich allows for triggering state change event or not * (depending on the caller). */ private void createTab(Dockable base, Dockable dockable, int order, boolean select, boolean triggerEvents){ /* createTab() is called by : * - DockView/DetachedDockView during DnD * - DockTabbedPane during DnD * - show() which is called by * - setFloating(false) * - setAutoHide(false) */ if (base == null)throw new NullPointerException("base must not be null"); if (dockable == null)throw new NullPointerException( "dockable must not be null"); DockableState currentState = getDockableState(dockable); int currentStateAsInt = getStateAsInt(currentState); // currentState might be null CLOSED HIDDEN DOCKED FLOATING DockableState newState = null ; // 2005/10/06 - support for floatable tabs : the future state can be docked or floating if (base.getDockKey().getDockableState() == DockableState.STATE_FLOATING){ RelativeDockablePosition position = new RelativeDockablePosition(dockingPanel, dockable); newState = new DockableState(this, dockable, base.getDockKey().getDockableState(), position); } else { newState = new DockableState(this, dockable, base.getDockKey().getDockableState()); } DockableStateWillChangeEvent dswe = new DockableStateWillChangeEvent(currentState, newState); DockingActionEvent dae = new DockingActionCreateTabEvent(this, dockable, currentStateAsInt, newState.getState(), base, order); //boolean stateChange = currentState == null || !currentState.isDocked(); //boolean stateChange = currentState == null || currentState.getState() != newState.getState(); //2005/10/07 if (triggerEvents){ if (! isDockingActionAccepted(dae, dswe)) { return; // vetoed } } TabbedDockableContainer dockableTab = null; if (currentStateAsInt != DockableState.STATE_CLOSED){ // don't search tabs for closed dockables // 2007/02/27 dockableTab = DockingUtilities.findTabbedDockableContainer(dockable); } // TabbedDockableContainer baseTab = DockingUtilities.findTabbedDockableContainer(dockable); // 2005/05/19 TabbedDockableContainer baseTab = DockingUtilities.findTabbedDockableContainer(base); // 2005/05/19 if (dockableTab != null && dockableTab != baseTab){ // don't belong to the same tabbed pane, so remove first the dockable remove(dockable); // TODO : check this : removal should have been done earlier (in dropRemove() ) } // if ( currentState != null && (!currentState.isFloating()) && newState.isFloating()){ if ( currentState != null && currentState.isFloating() && newState.isFloating()){ // this case is when dragging a floating dockable into another floating window Window w = SwingUtilities.getWindowAncestor(dockable.getComponent()); Window w2 = SwingUtilities.getWindowAncestor(base.getComponent()); if (w == null){ // the dockable has already been removed } else if (w != w2){ // when creating a floating tab, we have to manually remove the dockable remove(dockable); } else { // else same window : no need to remove it remove(dockable); } } else if ( currentState != null && (!currentState.isFloating()) && newState.isFloating()){ // from !floating to floating : // when creating a floating tab, we have to manually remove the dockable remove(dockable); } if (!newState.isFloating()){ // remove old attachment except when creating a floating tab removeFromTabbedGroup(dockable); // 2005/07/13 } if (baseTab != null){ // add a tab baseTab.addDockable(dockable, order); } else { // base isn't included in a tabbed pane, so we have to create one DockableContainer baseOldContainer = DockingUtilities.findSingleDockableContainer(base); baseTab = DockableContainerFactory.getFactory().createTabbedDockableContainer(); baseTab.installDocking(this); baseTab.addDockable(base,0); baseTab.addDockable(dockable,1); ((JTabbedPane) baseTab).addChangeListener(focusHandler); // our best way to track selection (focus) changes DockingUtilities.replaceChild(((Component)baseOldContainer).getParent(), (Component)baseOldContainer, (Component)baseTab); } if (select){ baseTab.setSelectedDockable(dockable); } context.registerDockable(dockable); context.setDockableState(dockable, newState); if (newState.isFloating() && !currentState.isFloating()){ // we need to store the return information storePreviousFloatingState(dockable, currentState); } if (triggerEvents){ dockable.getDockKey().setDockableState(base.getDockKey().getDockableState()); //2005/10/06 fireDockingAction(dae, new DockableStateChangeEvent(currentState, newState)); } if (!newState.isFloating()){ // register tab group association except if we are going floating... addToTabbedGroup(base, dockable); //2005/07/13 } DockingUtilities.updateResizeWeights(dockingPanel); } /** Splits a Dockable in 2 parts, if possible. *

* The base dockable is the reference, the second newDockable will be * added according to the position parameter. *

* If base is contained in a non splitable container (like a tab of DockTabbedPane) * then, a splitable ancestor will be searched (until the root desktop pane is reached) * to apply splitting. * * @param base an already docked Dockable * @param newDockable the added dockable * @param position position of newDockable relative to base */ public void split(Dockable base, Dockable newDockable, DockingConstants.Split position){ /* split() is used internally by the framework in the following cases : * - from a move() API invocation * - from a DnD on DockTabbedPane (overriding BorderSplitter) but only when the dockable is not floating * * => we can safely assume that the future state of the dockable will be "Docked" */ if (base == null) throw new NullPointerException("base must not be null"); if (newDockable == null) throw new NullPointerException("newDockable must not be null"); DockableState currentState = getDockableState(newDockable); int currentStateAsInt = getStateAsInt(currentState); boolean stateChange = currentState == null || !currentState.isDocked(); // todo : new state should be DOCKED *OR* FLOATING DockableState newState = new DockableState(this, newDockable, DockableState.STATE_DOCKED); DockingActionEvent dae = new DockingActionSplitDockableEvent(this, newDockable, currentStateAsInt, newState.getState(), base, position, 0.5f); DockableStateWillChangeEvent event = new DockableStateWillChangeEvent( currentState, newState); if (!isDockingActionAccepted(dae,event)) { return; // vetoed } TabbedDockableContainer baseTab = DockingUtilities.findTabbedDockableContainer(base); DockableContainer dockableContainer = DockableContainerFactory.getFactory(). createDockableContainer(newDockable, DockableContainerFactory.PARENT_SPLIT_CONTAINER); dockableContainer.installDocking(this); // create a new splitcontainer that will replace baseDockable's container SplitContainer split; if (position == DockingConstants.SPLIT_TOP || position == DockingConstants.SPLIT_BOTTOM){ split = new SplitContainer(JSplitPane.VERTICAL_SPLIT); } else /*if (position == DockingConstants.SPLIT_LEFT || position == DockingConstants.SPLIT_RIGHT)*/{ split = new SplitContainer(JSplitPane.HORIZONTAL_SPLIT); } Component left, right; // baseTab = null; // V2.1 TEST if (baseTab != null){ // base is contained in a tab, so the split will occur between the tab and // newDockable (a tabbed component cannot be splitted) DockingUtilities.replaceChild(((Component)baseTab).getParent(), ((Component)baseTab), split); if (position == DockingConstants.SPLIT_TOP || position == DockingConstants.SPLIT_LEFT){ left = (Component)dockableContainer; right = (Component)baseTab; } else { left = (Component)baseTab; right = (Component)dockableContainer; } } else { // base is not contained in a tab, so it must be a DockableContainer DockableContainer baseContainer = DockingUtilities.findSingleDockableContainer( base); assert baseContainer != null; DockingUtilities.replaceChild(((Component)baseContainer).getParent(), ((Component)baseContainer), split); if (position == DockingConstants.SPLIT_TOP || position == DockingConstants.SPLIT_LEFT){ left = (Component)dockableContainer; right = (Component)baseContainer; } else { left = (Component)baseContainer; right = (Component)dockableContainer; } } // now, we have to fill split with base and dockable split.setLeftComponent(left); split.setRightComponent(right); context.registerDockable(newDockable); context.setDockableState(newDockable, newState); newDockable.getDockKey().setDockableState(DockableState.STATE_DOCKED); fireDockingAction(dae, new DockableStateChangeEvent(currentState, newState)); removeFromTabbedGroup(newDockable); //2005/10/10 DockingUtilities.updateResizeWeights(dockingPanel); } /** Replaces the base component by a split pane oriented according to position, * and put dockable at position. *

* Note : This method is for DockableContainers. API users should * use the {@link #split(Dockable,Dockable,DockingConstants.Split) split} method. * * @param base the reference component (a dockablecontainer or a split container) * @param dockable the dockable to add * @param position the position of dockable. * * */ public void splitComponent(Component base, Dockable dockable, DockingConstants.Split position){ /* splitComponent() is called from SplitContainer and BorderSplitter * BorderSplitter is used by : * - DockView (not floating, as the DetachedDockView child overrides the scanDrop method and doesn't use the BorderSplitter * - DockTabbedPane (only when not floating) * SplitContainer is used for DnD operations that can occur from Hide/Docked/Floating elements * *=> The future state will be DOCKED, but we cannot guess the current state (HIDE/FLOAT/DOCKED) *=> as of 2.1 : the future state can be DOCKED or FLOATING (with the help of compound dockable) */ if (base == null) throw new NullPointerException("base"); if (dockable == null) throw new NullPointerException("dockable"); context.registerDockable(dockable); //int futureState = DockableState.STATE_DOCKED; int futureState = DockingUtilities.getDockableStateFromHierarchy(base); /*if (!dockingPanel.isAncestorOf(base)){ futureState = DockableState.STATE_FLOATING; }*/ DockableState currentState = getDockableState(dockable); int currentStateAsInt = getStateAsInt(currentState); boolean stateChange = false; if (currentState == null){ stateChange = true; } else if (currentState.getState() != futureState){ stateChange = true; } DockableState newState = new DockableState(this, dockable, futureState); // DockableState.STATE_DOCKED); DockableStateWillChangeEvent dswe = new DockableStateWillChangeEvent( currentState, newState); DockingActionEvent dae = new DockingActionSplitComponentEvent(this, dockable, currentStateAsInt, newState.getState(), base, position, 0.5f); if (!isDockingActionAccepted(dae, dswe)) { return; // vetoed } if (stateChange){ if (currentState.isFloating()){ removePreviousFloatingState(dockable); // clear reference of the previous state } } Container oldContainer = (Container)DockingUtilities.findSingleDockableContainer( dockable); int oldWidth = 0; int oldHeight = 0; if (oldContainer != null){ oldWidth = oldContainer.getWidth(); oldHeight = oldContainer.getHeight(); } else { oldWidth = base.getWidth() / 2; oldHeight = base.getHeight()/2; } DockableContainer dockableContainer = DockableContainerFactory.getFactory(). createDockableContainer(dockable, DockableContainerFactory.PARENT_SPLIT_CONTAINER); dockableContainer.installDocking(this); // create a new splitcontainer that will replace baseDockable's container SplitContainer split; if (position == DockingConstants.SPLIT_TOP || position == DockingConstants.SPLIT_BOTTOM){ split = new SplitContainer(JSplitPane.VERTICAL_SPLIT); } else /*if (position == DockingConstants.SPLIT_LEFT || position == DockingConstants.SPLIT_RIGHT)*/{ split = new SplitContainer(JSplitPane.HORIZONTAL_SPLIT); } if (base != dockingPanel){ // 2005/11/08 support for splitting from dockingPanel DockingUtilities.replaceChild(base.getParent(), base, split); if (position == DockingConstants.SPLIT_TOP || position == DockingConstants.SPLIT_LEFT){ split.setLeftComponent((Component)dockableContainer); split.setRightComponent(base); } else { split.setRightComponent((Component)dockableContainer); split.setLeftComponent(base); } } else { // docking panel must remain the top level ancestor if (dockingPanel.getComponentCount() != 0){ Component dockingPanelChild = dockingPanel.getComponent(0); DockingUtilities.replaceChild(dockingPanel, dockingPanelChild, split); if (position == DockingConstants.SPLIT_TOP || position == DockingConstants.SPLIT_LEFT){ split.setLeftComponent((Component)dockableContainer); split.setRightComponent(dockingPanelChild); } else { split.setRightComponent((Component)dockableContainer); split.setLeftComponent(dockingPanelChild); } } else { // dockingpanel is empty dockingPanel.add((Component) dockableContainer); } } // if (oldContainer != null){ // now try to keep same size as before the drop // we do this in invokelater because split.getWidth()/getHeight() returns 0 at this time // and we need this value to do a correct setDividerLocation. if (position == DockingConstants.SPLIT_TOP) { SwingUtilities.invokeLater(new SplitResizer(split, oldHeight)); } else if (position == DockingConstants.SPLIT_BOTTOM) { SwingUtilities.invokeLater(new SplitResizer(split, -oldHeight)); } else if (position == DockingConstants.SPLIT_LEFT) { SwingUtilities.invokeLater(new SplitResizer(split, oldWidth)); } else if (position == DockingConstants.SPLIT_RIGHT) { SwingUtilities.invokeLater(new SplitResizer(split, -oldWidth)); } // } context.setDockableState(dockable, newState); if (stateChange){ if (futureState == DockableState.STATE_FLOATING ){ // splitting from ? (should be Docked) to floating // we have to store a return state. storePreviousFloatingState(dockable, currentState); } } dockable.getDockKey().setDockableState(futureState); fireDockingAction(dae, new DockableStateChangeEvent(currentState, newState)); removeFromTabbedGroup(dockable); //2005/10/10 DockingUtilities.updateResizeWeights(dockingPanel); } /** Replaces the base component by a split pane oriented according to position, * and put the dockablesContainer at position. *

* Note : This method is for DockableContainers. API users should * use the {@link #split(Dockable,Dockable,DockingConstants.Split) split} method. * * @param base the reference component (a dockablecontainer or a split container) * @param dockablesContainer the dockable container * @param position the position of dockable. * * */ public void splitComponent(Component base, Container dockablesContainer, DockingConstants.Split position){ if (dockablesContainer instanceof SingleDockableContainer){ splitComponent(base, ((SingleDockableContainer)dockablesContainer).getDockable(), position); } else if (dockablesContainer instanceof TabbedDockableContainer){ splitTab(base, (TabbedDockableContainer)dockablesContainer, position); } else { System.err.println("unknow split request !" + dockablesContainer ); } } private void splitTab(Component base, TabbedDockableContainer tdc, DockingConstants.Split position){ // should be used only when drag and dropping if (base == null) throw new NullPointerException("base"); Dockable firstDockable = tdc.getDockableAt(0); DockableState currentState = getDockableState(firstDockable); boolean stateChange = false; if (currentState.isFloating()){ removePreviousFloatingStates(tdc); // clear reference of the previous state stateChange = true; } Container oldContainer = (Container)tdc; int oldWidth = 0; int oldHeight = 0; if (oldContainer != null){ oldWidth = oldContainer.getWidth(); oldHeight = oldContainer.getHeight(); } else { oldWidth = base.getWidth() / 2; oldHeight = base.getHeight()/2; } DockableContainer dockableContainer = tdc; // create a new splitcontainer that will replace baseDockable's container SplitContainer split; if (position == DockingConstants.SPLIT_TOP || position == DockingConstants.SPLIT_BOTTOM){ split = new SplitContainer(JSplitPane.VERTICAL_SPLIT); } else /*if (position == DockingConstants.SPLIT_LEFT || position == DockingConstants.SPLIT_RIGHT)*/{ split = new SplitContainer(JSplitPane.HORIZONTAL_SPLIT); } if (base != dockingPanel){ // 2005/11/08 support for splitting from dockingPanel DockingUtilities.replaceChild(base.getParent(), base, split); if (position == DockingConstants.SPLIT_TOP || position == DockingConstants.SPLIT_LEFT){ split.setLeftComponent((Component)dockableContainer); split.setRightComponent(base); } else { split.setRightComponent((Component)dockableContainer); split.setLeftComponent(base); } } else { // docking panel must remain the top level ancestor if (dockingPanel.getComponentCount() != 0){ Component dockingPanelChild = dockingPanel.getComponent(0); DockingUtilities.replaceChild(dockingPanel, dockingPanelChild, split); if (position == DockingConstants.SPLIT_TOP || position == DockingConstants.SPLIT_LEFT){ split.setLeftComponent((Component)dockableContainer); split.setRightComponent(dockingPanelChild); } else { split.setRightComponent((Component)dockableContainer); split.setLeftComponent(dockingPanelChild); } } else { // dockingpanel is empty dockingPanel.add((Component) dockableContainer); } } //if (oldContainer != null){ // now try to keep same size as before the drop // we do this in invokelater because split.getWidth()/getHeight() returns 0 at this time // and we need this value to do a correct setDividerLocation. if (position == DockingConstants.SPLIT_TOP) { SwingUtilities.invokeLater(new SplitResizer(split, oldHeight)); } else if (position == DockingConstants.SPLIT_BOTTOM) { SwingUtilities.invokeLater(new SplitResizer(split, -oldHeight)); } else if (position == DockingConstants.SPLIT_LEFT) { SwingUtilities.invokeLater(new SplitResizer(split, oldWidth)); } else if (position == DockingConstants.SPLIT_RIGHT) { SwingUtilities.invokeLater(new SplitResizer(split, -oldWidth)); } //} if (stateChange){ // this part is tricky : we assume the caller is DragContoller (it's the only // legal way to invoke this method). DragController triggers event change for (int i=0; i < tdc.getTabCount(); i++){ Dockable d = tdc.getDockableAt(i); DockableState newState = new DockableState(this, d, DockableState.STATE_DOCKED); context.setDockableState(d, newState); } } // registerDockable(dockable); // dockableStates.put(dockable, newState); // if (stateChange){ // dockable.getDockKey().setDockableState(DockableState.STATE_DOCKED); // fireDockableStateChange(new DockableStateChangeEvent(currentState, newState)); // } // // removeFromTabbedGroup(dockable); //2005/10/10 // DockingUtilities.updateResizeWeights(dockingPanel); } /** Moves a dockable to another position (relative to a destination dockable) * * * @param dockable must be a registered Dockable * @param base must be a visible Dockable * @param position relative positionning */ public void move(Dockable base, Dockable dockable, DockingConstants.Split position){ if (base == null) throw new NullPointerException("base must not be null"); if (dockable == null) throw new NullPointerException("dockable must not be null"); if (dockable == base) return; remove(dockable); removeFromTabbedGroup(dockable); // 2005/07/13 split(base, dockable, position); } /** Shows again a dockable (if previously hidden, floating or closed). *

* The dockable is inserted in the docking desktop where it was before, if possible. * if not, an approximated place will be looked for. * */ private void show(Dockable dockable, DockingActionEvent action){ if (dockable == null) throw new NullPointerException("dockable must not be null"); DockableState state = context.getDockableState(dockable); RelativeDockablePosition position = state.getPosition(); if (position == null){ // not shown before, ask best position to the preferences // TODO throw new NullPointerException("trying to show a view that was not hidden"); } LinkedList group = (LinkedList) tabbedGroups.get(dockable); //2005/07/13... boolean tabbed = false; if (group != null){ // look for a still visible dockable in the group Iterator it = group.iterator(); while (it.hasNext() && ! tabbed){ Dockable d = (Dockable) it.next(); if (d != dockable && getDockableState(d).isDocked()){ createTab(d, dockable, Integer.MAX_VALUE, true, false); tabbed = true; } } } if (! tabbed){ // ...2005/07/13 SingleDockableContainer sdc = RelativeDockingUtilities.applyDockingAction(dockable, action); // SingleDockableContainer sdc = RelativeDockingUtilities.insertDockable( // position.getRelativeAncestorContainer(), dockable, position); sdc.installDocking(this); } } /** Removes a visible dockable from the containment hierarchy (including autohide border buttons). *

* This method shouldn't be used by user applications (only by the framework). *

* To poperly remove a component from the desktop, use the close(Dockable) method instead *

* If the dockable is not visible, an error will occur *

* This method does not unregister the dockable. * * @throws IllegalArgumentException if the dockable is not visible (docked or auto-hide) * */ public void remove(Dockable dockable) { // TODO : check this : split this method in two (removeImpl() should be used form inside the framework, and // remove should trigger CLOSE state change events //if (dockingPanel.isAncestorOf(dockable.getComponent())){ //2005/10/06 ... int dockState = dockable.getDockKey().getDockableState(); SingleDockableContainer dockableContainer = null; Container parentOfSdc = null; boolean isChildOfCompoundDockable = false; // v2.1 if ( dockState == DockableState.STATE_DOCKED || dockState == DockableState.STATE_FLOATING){ // ...2005/10/06 // we must guess that before removing the dockable from its parent... isChildOfCompoundDockable = DockingUtilities.isChildOfCompoundDockable(dockable); dockableContainer = DockingUtilities.findSingleDockableContainer(dockable); parentOfSdc = ((JComponent)dockableContainer).getParent(); removeContainer(dockableContainer); } if (dockState == DockableState.STATE_FLOATING){ FloatingDockableContainer fdc = (FloatingDockableContainer) SwingUtilities.getWindowAncestor(dockable.getComponent()); if (parentOfSdc instanceof TabbedDockableContainer){ // dockable was contained in a tab on the floatable : we must not dispose the window } else if (isChildOfCompoundDockable){ // dockable was a child of a compound dockable : don't dispose } else { DockingUtilities.dispose(fdc); //((JDialog)dlg).dispose(); } } else if (dockState == DockableState.STATE_HIDDEN){ // DockableState state = (DockableState) dockableStates.get(dockable); // if (state.isHidden()) { // component is removed from the auto-hide list //dockableStates.put(dockable, new DockableState(dockable, DockableState.STATE_CLOSED)); // 2005/10/10 removed this : wrong place to change a dockable state AutoHideButton btn = (AutoHideButton) autoHideButtons.get(dockable. getDockKey()); if (btn == null){ // (v2.1) no button : that means this dockable is a child of a hidden compound dockable // so we just use the standard removing pattern dockableContainer = DockingUtilities.findSingleDockableContainer(dockable); parentOfSdc = ((JComponent)dockableContainer).getParent(); removeContainer(dockableContainer); } else { // single auto-hide dockable btn.setVisible(false); expandPanel.remove(dockable); // in case the dockable was the current visible dockable } revalidate(); /* } else if (state.isFloating()){ Window w = SwingUtilities.getWindowAncestor(dockable.getComponent()); w.dispose(); } else { // well, it's not shown, and not hidden... // nop }*/ } } /** Removes a visible dockable : called from a drag and drop operation. *

Don't call this method directly, as it is meant to be used only by the drag and drop * event components. */ public void dropRemove(DockableDragSource dragSource){ // before removing the dockable, we update its state to store its new relative position Dockable d = dragSource.getDockable(); DockableState state = context.getDockableState(d); if (state != null){ // some drag source don't have state associated with them (like whole TabbedContainers) DockableState updatedState = new DockableState(state, new RelativeDockablePosition(getRelativeAncestorContainer(d), d)); context.setDockableState(dragSource.getDockable(), updatedState); } Container dockableContainer = dragSource.getDockableContainer(); if (dockableContainer instanceof TabbedDockableContainer){ remove((TabbedDockableContainer)dockableContainer); } else { remove(dragSource.getDockable()); } //removeFromTabbedGroup(dockable); 2005/10/10 don't remove from tab : it's too early to be sure we won't need it again // for example : when removing from a tab to create a floating tab (we have to keep the old attachment) } /** Removes a whole tab container (which is beeing moved to somewhere else) *

* This operation is done only during a drag and drop process. * * @throws IllegalArgumentException if the dockable is not visible (docked or auto-hide) * */ private void remove(TabbedDockableContainer tdc) { // TODO : check this : split this method in two (removeImpl() should be used form inside the framework, and // remove should trigger CLOSE state change events Dockable firstDockable = tdc.getDockableAt(0); //if (dockingPanel.isAncestorOf(dockable.getComponent())){ //2005/10/06 ... int dockState = firstDockable.getDockKey().getDockableState(); if (dockState == DockableState.STATE_FLOATING){ FloatingDockableContainer fdc = (FloatingDockableContainer) SwingUtilities.getWindowAncestor((Container) tdc); DockingUtilities.dispose(fdc); //((JDialog)dlg).dispose(); } boolean invalidateDesktop = true; // always, except for floating dockables Component parent = ((Component)tdc).getParent(); if (parent != null){ if (parent instanceof SplitContainer) { SplitContainer viewParent = (SplitContainer) parent; if (viewParent.getLeftComponent() == tdc) { viewParent.remove((Component)tdc); Component other = viewParent.getRightComponent(); // replace viewParent by other in viewParent's hierarchy Container viewGParent = (Container) viewParent.getParent(); DockingUtilities.replaceChild(viewGParent, viewParent, other); } else { viewParent.remove((Component)tdc); Component other = viewParent.getLeftComponent(); Container viewGParent = (Container) viewParent.getParent(); DockingUtilities.replaceChild(viewGParent, viewParent, other); } } else if (parent == dockingPanel) { // no more views to show dockingPanel.remove(0); } else if (SwingUtilities.getWindowAncestor(parent) instanceof FloatingDockableContainer){ // removing from a FloatingDockableContainer... nothing to do invalidateDesktop = false; } else { throw new IllegalStateException("View is not contained in desktop hierarchy " + parent); } if (invalidateDesktop){ dockingPanel.invalidate(); dockingPanel.validate(); dockingPanel.repaint(); } } } /** Extends the size of this dockable to fill the docking panel. *

* The component must be docked before beeing maximized, otherwise an IllegalArgumentException will * be thrown. *

* The opposite method of maximize is restore(Dockable). * @see #restore(Dockable) * */ public void maximize(Dockable dockable){ if (dockable.getDockKey().getDockableState() != DockableState.STATE_DOCKED){ // development error (could have been an assertion). throw new IllegalArgumentException("Dockable isn't currently in the DOCKED state : " + dockable); } DockableState currentState = getDockableState(dockable); boolean stateChange = currentState == null || !currentState.isMaximized(); DockableState newState = new DockableState(this, dockable, DockableState.STATE_MAXIMIZED); int currentStateAsInt = getStateAsInt(currentState); DockableStateWillChangeEvent dswe = new DockableStateWillChangeEvent( currentState, newState); DockingActionEvent dae = new DockingActionSimpleStateChangeEvent(this, dockable, currentStateAsInt, DockableState.STATE_MAXIMIZED); if (!isDockingActionAccepted(dae, dswe)){ return; // vetoed } // v2.1 : if the currently maximized dockable is a compound dockable, than its children // can still be maximized. // to avoid "stacking" maximized component, we just "restore" the compound dockable SingleDockableContainer currentMaximizedContainer = (SingleDockableContainer)maximizedComponent; if (currentMaximizedContainer != null && currentMaximizedContainer.getDockable() != dockable){ // there's already a dockable which is maximized : restore it first restore(currentMaximizedContainer.getDockable()); } SingleDockableContainer sdc = DockingUtilities.findSingleDockableContainer(dockable); Component dockableContainer = (Component) sdc; DockingUtilities.replaceChild(dockableContainer.getParent(), dockableContainer, dummyMaximedReplacer); SingleDockableContainer maxDockableContainer = DockableContainerFactory.getFactory() .createDockableContainer(dockable, DockableContainerFactory.PARENT_DESKTOP); maxDockableContainer.installDocking(this); this.maximizedComponent = (Component) maxDockableContainer; Insets i = getDockingPanelInsets(); if (DockingPreferences.isLightWeightUsageEnabled()){ maximizedComponent.setBounds(i.left,i.top, getWidth() - i.left - i.right, getHeight() - i.top - i.bottom); add(maximizedComponent, JLayeredPane.PALETTE_LAYER); } else { this.currentMaximizedComponentIsHeavyWeight = false; if (DockingPreferences.isSingleHeavyWeightComponent()){ // first, check if the heavyweight component IS this dockable Component comp = dockable.getComponent(); //2005/10/20 support for single heavyweight if (DockingUtilities.isHeavyWeightComponent(comp)){ // it's the heavyweight component (and the only one) // so we just have to put it there (no need for an in-between awt panel) maximizedComponent.setBounds(i.left,i.top, getWidth() - i.left - i.right, getHeight() - i.top - i.bottom); add(maximizedComponent, JLayeredPane.PALETTE_LAYER); currentMaximizedComponentIsHeavyWeight = true; } else { // this one is not the heavyweight : we have to put it on top of a fresh awt Panel Panel awtPanel = new Panel(new BorderLayout()); awtPanel.setBounds(i.left,i.top, getWidth() - i.left - i.right, getHeight() - i.top - i.bottom); awtPanel.add(maximizedComponent, BorderLayout.CENTER); awtPanel.validate(); add(awtPanel, JLayeredPane.PALETTE_LAYER); } } else { // if there are heavyweight components around, we need to add an in-between // awt Panel to avoid those components to be drawn on top of the maximized component Panel awtPanel = new Panel(new BorderLayout()); awtPanel.setBounds(i.left,i.top, getWidth() - i.left - i.right, getHeight() - i.top - i.bottom); awtPanel.add(maximizedComponent, BorderLayout.CENTER); awtPanel.validate(); add(awtPanel, JLayeredPane.PALETTE_LAYER); } } context.setDockableState(dockable, newState); dockable.getDockKey().setDockableState(DockableState.STATE_MAXIMIZED); fireDockingAction(dae, new DockableStateChangeEvent(currentState, newState)); dockable.getComponent().requestFocus(); repaint(); } /** Restore the dockable to the docking position it was before beeing maximized. *

* The dockable must be already maximized (otherwise an IllegalArgumentException will be thrown) * * @see #maximize(Dockable) * */ public void restore(final Dockable dockable){ if (dockable.getDockKey().getDockableState() != DockableState.STATE_MAXIMIZED){ // development error (could have been an assertion). throw new IllegalArgumentException("Dockable isn't currently in the MAXIMIZED state : " + dockable); } DockableState currentState = getDockableState(dockable); boolean stateChange = currentState != null || currentState.isMaximized(); DockableState newState = new DockableState(this, dockable, DockableState.STATE_DOCKED); int currentStateAsInt = getStateAsInt(currentState); DockableStateWillChangeEvent dswe = new DockableStateWillChangeEvent( currentState, newState); DockingActionEvent dae = new DockingActionSimpleStateChangeEvent(this, dockable, currentStateAsInt, DockableState.STATE_DOCKED); if (! isDockingActionAccepted(dae, dswe)){ return; // vetoed } if (!DockingPreferences.isLightWeightUsageEnabled()){ if (DockingPreferences.isSingleHeavyWeightComponent() && this.currentMaximizedComponentIsHeavyWeight){ // 2005/10/20 remove(maximizedComponent); } else { remove(maximizedComponent.getParent()); // remove the awt panel } } else { remove(maximizedComponent); } ((SingleDockableContainer) maximizedComponent ).uninstallDocking(this); SingleDockableContainer sdc = null; if (dummyMaximedReplacer.getParent() instanceof TabbedDockableContainer){ sdc = DockableContainerFactory.getFactory().createDockableContainer(dockable, DockableContainerFactory.PARENT_TABBED_CONTAINER); } else { sdc = DockableContainerFactory.getFactory().createDockableContainer(dockable, DockableContainerFactory.PARENT_SPLIT_CONTAINER); } DockingUtilities.replaceChild(dummyMaximedReplacer.getParent(), dummyMaximedReplacer, (Component)sdc); context.setDockableState(dockable, newState); dockable.getDockKey().setDockableState(DockableState.STATE_DOCKED); fireDockingAction(dae, new DockableStateChangeEvent(currentState, newState)); SwingUtilities.invokeLater(new Runnable(){ public void run(){ dockable.getComponent().requestFocus(); } }); sdc.installDocking(this); maximizedComponent = null; repaint(); } /** Detach or attach the dockable from/to the desktop. *

* When detached, the dockable is centered on the desktop. */ public void setFloating(final Dockable dockable, boolean floating){ setFloating(dockable, floating, null); } /** Used only with DOCKED dockables : returns the nearest ancestor container * (can be a CompoundDockingPanel if nested, or the DockingPanel). */ private Container getRelativeAncestorContainer(Dockable dockable){ Container compoundAncestor = DockingUtilities.findCompoundAncestorContainer(dockable); if (compoundAncestor != null){ return compoundAncestor; } else { return dockingPanel; } } /** Detach or attach the dockable from/to the desktop. *

* show the dockable at sceenPosition (when not null) or centered (if screenPosition is null) * */ public void setFloating(final Dockable dockable, boolean floating, Point screenPosition){ if (dockable == null)throw new NullPointerException("dockable"); DockableState currentState = getDockableState(dockable); int currentStateAsInt = getStateAsInt(currentState); SingleDockableContainer dockableContainer = DockingUtilities. findSingleDockableContainer(dockable); if (floating){ int state = dockable.getDockKey().getDockableState(); RelativeDockablePosition position = null; if (state == DockableState.STATE_DOCKED){ position = new RelativeDockablePosition(getRelativeAncestorContainer(dockable), dockable); } else if (state == DockableState.STATE_HIDDEN){ position = currentState.getPosition(); // get the position that was stored before } else if (state == DockableState.STATE_FLOATING){ // from floating..to floating. It's still possible, if the component was previously tabbed (now it will have its // own window if (DockingUtilities.findTabbedDockableContainer(dockable) != null){ // ok, it was tabbed and floating } else { throw new IllegalArgumentException("floating not tabbed"); } } else if (state == DockableState.STATE_CLOSED){ return; // ignore : to detach a dockable it must be somehow visible //2006/02/20 } else { throw new IllegalArgumentException("not docked " + state); } DockableState newState = new DockableState(this, dockable, DockableState.STATE_FLOATING, position); DockableStateWillChangeEvent event = new DockableStateWillChangeEvent(currentState, newState); if (state == DockableState.STATE_FLOATING){ // floating to floating (create a new floating dialog by removing a dockable from a detached tab) // note (@todo): as of version 2.1, we should trigger a dockingActionEvent here... but which one ? // an addDockable with a floating state ? Dimension previousSize = null; remove(dockable); if (dockableContainer !=null){ previousSize = ((Component)dockableContainer).getSize(); } FloatingDockableContainer fdc = createFloatingDockableContainer(dockable); //JDialog dialog = (JDialog) fdc; if (previousSize != null){ DockingUtilities.setSize(fdc, previousSize); //2006/02/20 DockingUtilities.validate(fdc); //dialog.setSize(previousSize); //dialog.validate(); } else { DockingUtilities.pack(fdc); //dialog.pack(); } if (screenPosition == null){ DockingUtilities.setLocationRelativeTo(fdc, this); //dialog.setLocationRelativeTo(this); } else { DockingUtilities.setLocation(fdc, screenPosition); //dialog.setLocation(screenPosition); } DockingUtilities.setVisible(fdc, true); //dialog.setVisible(true); } else if (currentState != null){ DockingActionEvent dae = new DockingActionSimpleStateChangeEvent(this, dockable, currentStateAsInt, DockableState.STATE_FLOATING); if (isDockingActionAccepted(dae, event)){ // not already floating so we trigger state events Dimension previousSize = null; if (dockableContainer !=null){ previousSize = ((Component)dockableContainer).getSize(); } remove(dockable); // store a return state, based on the current state + updated relative position storePreviousFloatingState(dockable, new DockableState(currentState, position)); FloatingDockableContainer fdc = createFloatingDockableContainer(dockable); //JDialog dialog = (JDialog) fdc; if (previousSize != null){ DockingUtilities.setSize(fdc, previousSize); DockingUtilities.validate(fdc); //dialog.setSize(previousSize); //dialog.validate(); } else { DockingUtilities.pack(fdc); //dialog.pack(); } if (screenPosition == null){ DockingUtilities.setLocationRelativeTo(fdc, this); //dialog.setLocationRelativeTo(this); } else { DockingUtilities.setLocation(fdc, screenPosition); //dialog.setLocation(screenPosition); } DockingUtilities.setVisible(fdc, true); //dialog.setVisible(true); context.setDockableState(dockable, newState); dockable.getDockKey().setDockableState(DockableState.STATE_FLOATING); fireDockingAction(dae, new DockableStateChangeEvent(currentState, newState)); if (dockable instanceof CompoundDockable){ updateCompoundChildrenState((CompoundDockable)dockable, DockableState.STATE_FLOATING); } DockingUtilities.updateResizeWeights(dockingPanel); revalidate(); } } } else { // attach ! // remove the button, show again the view // was the dockable docked or hidden ? DockableState previousState = getPreviousDockableState(dockable); DockableState newState = new DockableState(this, dockable, previousState.getState(), previousState.getPosition()); DockableStateWillChangeEvent event = new DockableStateWillChangeEvent(currentState, newState); DockingActionEvent dae; if (currentState != null && currentState.isFloating()){ if (previousState.isDocked()){ RelativeDockablePosition prevPos = previousState.getPosition(); Container relativeAncestor = prevPos.getRelativeAncestorContainer(); if (relativeAncestor == null){ relativeAncestor = dockingPanel; // safety : @todo we have to refactor xmlBuildFloatingNode to // store the relativeAncestorContainer } dae = RelativeDockingUtilities.getInsertionDockingAction( relativeAncestor, dockable, currentState, newState); } else if (previousState.isHidden()){ // it was hidden dae = new DockingActionSimpleStateChangeEvent(this, dockable, DockableState.STATE_FLOATING, DockableState.STATE_HIDDEN); } else { // shoudn't be possible throw new RuntimeException(); } if (isDockingActionAccepted(dae, event)){ removePreviousFloatingState(dockable); Container parentOfSdc = null; //2005/10/07 parentOfSdc = ((JComponent)dockableContainer).getParent(); removeContainer(dockableContainer); FloatingDockableContainer fdc = (FloatingDockableContainer) SwingUtilities.getWindowAncestor(dockable.getComponent()); if (parentOfSdc instanceof TabbedDockableContainer){ // dockable was contained in a tab on the floatable : we must not dispose the window } else { DockingUtilities.dispose(fdc); //((JDialog)fdc).dispose(); } context.setDockableState(dockable, newState); if (previousState.isDocked()){ show(dockable, dae); // TODO Fix this null } else if (previousState.isHidden()){ // it was hidden floatingToHide(dockable, previousState.getPosition()); } else { // unmanaged state throw new RuntimeException(); } dockable.getDockKey().setDockableState(previousState.getState()); fireDockingAction(dae, new DockableStateChangeEvent(currentState, newState)); dockable.getComponent().requestFocus(); if (dockable instanceof CompoundDockable){ updateCompoundChildrenState((CompoundDockable)dockable, newState.getState()); } DockingUtilities.updateResizeWeights(dockingPanel); revalidate(); } } } } /** Detach or attach a whole tabbed dockable container from/to the desktop. *

* displays the component at sceenPosition (when not null) or centered (if screenPosition is null) * */ void setFloating(final TabbedDockableContainer tdc, Point screenPosition){ /* package protected, used by DragControler to detach a tabbedcontainer */ Dockable firstDockable = tdc.getDockableAt(0); // all dockables have the same state, as they are in the same tabpane DockableState currentState = getDockableState(firstDockable); if (!currentState.isDocked()){ throw new IllegalArgumentException("not docked"); } else { if (checkDockableStateWillChange(tdc, DockableState.STATE_FLOATING)){ RelativeDockablePosition position = new RelativeDockablePosition(dockingPanel, firstDockable); // no veto has been raised by the compound dockables Dimension previousSize = ((Component)tdc).getSize(); remove(tdc); storePreviousFloatingStates(tdc); FloatingDockableContainer fdc = createFloatingDockableContainer(tdc); //JDialog dialog = (JDialog) fdc; //dialog.setSize(previousSize); //dialog.validate(); DockingUtilities.setSize(fdc, previousSize); DockingUtilities.validate(fdc); if (screenPosition == null){ DockingUtilities.setLocationRelativeTo(fdc, this); //dialog.setLocationRelativeTo(this); } else { DockingUtilities.setLocation(fdc, screenPosition); //dialog.setLocation(screenPosition); } DockingUtilities.setVisible(fdc, true); //dialog.setVisible(true); fireStateChanged(tdc, DockableState.STATE_FLOATING, position); DockingUtilities.updateResizeWeights(dockingPanel); revalidate(); } } } private void storePreviousFloatingStates(TabbedDockableContainer tdc){ for (int i=0; i < tdc.getTabCount(); i++){ Dockable d = tdc.getDockableAt(i); DockableState current = getDockableState(d); storePreviousFloatingState(d, current); } } private boolean checkDockableStateWillChange(TabbedDockableContainer tdc, int futureState){ for (int i=0; i < tdc.getTabCount(); i++){ Dockable d = tdc.getDockableAt(i); DockableState currentState = getDockableState(d); int currentStateAsInt = getStateAsInt(currentState); DockableState newState = new DockableState(this, d, futureState, null); DockableStateWillChangeEvent event = new DockableStateWillChangeEvent(currentState, newState); DockingActionEvent dae = new DockingActionSimpleStateChangeEvent(this, d, currentStateAsInt, newState.getState()); if (!isDockingActionAccepted(dae,event)){ return false; } } return true; } private void fireStateChanged(TabbedDockableContainer tdc, int futureState, RelativeDockablePosition position){ for (int i=0; i < tdc.getTabCount(); i++){ Dockable d = tdc.getDockableAt(i); DockableState currentState = getDockableState(d); int currentStateAsInt = getStateAsInt(currentState); DockableState newState = new DockableState(this, d, futureState, position); context.setDockableState(d, newState); d.getDockKey().setDockableState(DockableState.STATE_FLOATING); DockingActionEvent dae = new DockingActionSimpleStateChangeEvent(this, d, currentStateAsInt, newState.getState()); fireDockingAction(dae, new DockableStateChangeEvent(currentState, newState)); } } private DockableState removePreviousFloatingStates(TabbedDockableContainer tdc){ DockableState first = removePreviousFloatingState(tdc.getDockableAt(0)); for (int i=1; i < tdc.getTabCount(); i++){ Dockable d = tdc.getDockableAt(i); removePreviousFloatingState(d); } return first; } /** Returns the previous state of a hidden or floating dockable (when that dockable * was in the DOCKED state. *@since 2.0.4 * */ public DockableState getPreviousDockableState(Dockable dockable){ /* method mostly used internally */ return (DockableState) previousFloatingDockableStates.get(dockable); } private DockableState removePreviousFloatingState(Dockable dockable){ if (dockable instanceof CompoundDockable){ // we also need to clear states of the compound children ArrayList children = DockingUtilities.findCompoundDockableChildren((CompoundDockable)dockable); for (int i=0; i < children.size(); i++){ Dockable d = (Dockable) children.get(i); previousFloatingDockableStates.remove(d); } } return (DockableState) previousFloatingDockableStates.remove(dockable); } private void storePreviousFloatingState(Dockable dockable, DockableState state){ // when storing a previous dockable state before going floating, we have // to ensure the relativeDockableAncestorContainer is defined RelativeDockablePosition pos = state.getPosition(); if (pos.getRelativeAncestorContainer() == null){ Container c = DockingUtilities.findCompoundAncestorContainer(dockable); if (c != null){ pos.resetRelativePosition(c, dockable); } else { pos.resetRelativePosition(dockingPanel, dockable); } } previousFloatingDockableStates.put(dockable, state); if (dockable instanceof CompoundDockable){ // more to do : the compund dockable may have children : they will share the // same return position ArrayList children = DockingUtilities.findCompoundDockableChildren((CompoundDockable)dockable); for (int i=0; i < children.size(); i++){ Dockable d = (Dockable) children.get(i); previousFloatingDockableStates.put(d, new DockableState(this, d, state.getState(), state.getPosition())); } } } /** simplified auto-hide version used when the dockable was previously in FLOATING state */ private void floatingToHide(Dockable dockable, RelativeDockablePosition position){ // doesn't trigger change event as it is managed by setFloatin(false) DockKey k = dockable.getDockKey(); AutoHideButton btn = (AutoHideButton) autoHideButtons.get(k); if (btn == null) { btn = new AutoHideButton(); autoHideButtons.put(k, btn); int zone; if (k.getAutoHideBorder() == null) { zone = AutoHidePolicy.getPolicy().getDefaultHideBorder().value(); } else { zone = k.getAutoHideBorder().value(); } btn.init(dockable, zone); borderPanes[zone].setVisible(true); // border may not be visible borderPanes[zone].add(btn); borderPanes[zone].revalidate(); } else { // btn already existing, show it again int zone = btn.getZone(); borderPanes[zone].setVisible(true); // may not be visible btn.setVisible(true); borderPanes[zone].revalidate(); } } private void moveFloatingWindows(){ //2005/10/10 Window w = SwingUtilities.getWindowAncestor(this); if (w == null){ return; // 2007/02/27 fixed NPE } Point newLocation = w.getLocation(); if (this.lastWindowLocation != null){ int dx = newLocation.x - lastWindowLocation.x; int dy = newLocation.y - lastWindowLocation.y; Window [] childWindow = w.getOwnedWindows(); for (int i=0; i < childWindow.length; i++){ if (childWindow[i] instanceof FloatingDockableContainer && childWindow[i].isVisible()){ Point p = childWindow[i].getLocation(); childWindow[i].setLocation(p.x + dx, p.y +dy); } } } lastWindowLocation = newLocation; } /** Creates a floating JDialog to be used with this dockable. *

* This method is protected to give access to implementors wanting to * customize its look and feel (for example : removing the title bar by * setting it to "undecorated"). *

* The old API has been removed (it returned a JDialog) as the DockingDesktop can only * work with FloatingDockableContainers. */ protected FloatingDockableContainer createFloatingDockableContainer(final Dockable dockable){ Window ownerWindow = SwingUtilities.getWindowAncestor(this); FloatingDockableContainer fdc = DockableContainerFactory.getFactory().createFloatingDockableContainer(ownerWindow); fdc.installDocking(this); fdc.setInitialDockable(dockable); //JDialog dialog = (JDialog) fdc; KeyStroke ks = (KeyStroke) UIManager.get("DockingDesktop.floatActionAccelerator"); if (ks != null){ JRootPane root = DockingUtilities.getRootPane(fdc); root.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(ks, "float"); root.getActionMap().put("float", floatAction); } // dialog.pack(); // dialog.setVisible(true); return fdc; } /** Creates a floating JDialog to be used for a whole TabbedDockableContainer. *

* This method is protected to give access to implementors wanting to * customize its look and feel (for example : removing the title bar by * setting it to "undecorated"). *

* The old API has been removed (it returned a JDialog) as the DockingDesktop can only * work with FloatingDockableContainers. */ protected FloatingDockableContainer createFloatingDockableContainer(TabbedDockableContainer tdc){ Window ownerWindow = SwingUtilities.getWindowAncestor(this); FloatingDockableContainer fdc = DockableContainerFactory.getFactory().createFloatingDockableContainer(ownerWindow); fdc.installDocking(this); fdc.setInitialTabbedDockableContainer(tdc); //JDialog dialog = (JDialog) fdc; KeyStroke ks = (KeyStroke) UIManager.get("DockingDesktop.floatActionAccelerator"); if (ks != null){ JRootPane root = DockingUtilities.getRootPane(fdc); root.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(ks, "float"); root.getActionMap().put("float", floatAction); } // dialog.pack(); // dialog.setVisible(true); return fdc; } /** Removes a dockable container. */ protected void removeContainer(SingleDockableContainer dc){ /* to be improved : this method supposes a direct ancestor link between DockableContainer and TabbedDockableContainer */ dc.uninstallDocking(this); boolean invalidateDesktop = true; // always, except for floating dockables Component parent = ((Component)dc).getParent(); if (parent != null){ if (parent instanceof SplitContainer) { SplitContainer viewParent = (SplitContainer) parent; if (viewParent.getLeftComponent() == dc) { viewParent.remove((Component)dc); Component other = viewParent.getRightComponent(); // replace viewParent by other in viewParent's hierarchy Container viewGParent = (Container) viewParent.getParent(); DockingUtilities.replaceChild(viewGParent, viewParent, other); } else { viewParent.remove((Component)dc); Component other = viewParent.getLeftComponent(); Container viewGParent = (Container) viewParent.getParent(); DockingUtilities.replaceChild(viewGParent, viewParent, other); } } else if (parent instanceof TabbedDockableContainer) { TabbedDockableContainer tparent = (TabbedDockableContainer) parent; tparent.removeDockable(dc.getDockable()); if (tparent.getTabCount() == 1) { // no more use for tabs tparent.uninstallDocking(this); ((JTabbedPane)tparent).removeChangeListener(focusHandler); Dockable last = tparent.getDockableAt(0); boolean floating = last.getDockKey().getDockableState() == DockableState.STATE_FLOATING; DockableContainer lastContainer = null; if (floating) { lastContainer = DockableContainerFactory.getFactory(). createDockableContainer(last, DockableContainerFactory.PARENT_DETACHED_WINDOW); } else { lastContainer = DockableContainerFactory.getFactory(). createDockableContainer(last, DockableContainerFactory.PARENT_SPLIT_CONTAINER); } lastContainer.installDocking(this); DockingUtilities.replaceChild( ( (Component) tparent).getParent(), (Component) tparent, (Component)lastContainer); } } else if (parent == dockingPanel) { // no more views to show dockingPanel.remove(0); } else if (SwingUtilities.getWindowAncestor(parent) instanceof FloatingDockableContainer){ // removing from a FloatingDockableContainer... nothing to do invalidateDesktop = false; } else { ((Container) parent).remove((Component)dc); //throw new IllegalStateException("View is not contained in desktop hierarchy " + parent); } if (invalidateDesktop){ dockingPanel.invalidate(); dockingPanel.validate(); dockingPanel.repaint(); } } } /** Returns the current state of a dockable (CLOSED, HIDDEN, DOCKED, MAXIMIZED, FLOATING) */ public DockableState getDockableState(Dockable dockable){ return context.getDockableState(dockable); } /** Disposes the dockable container of this dockable. *

If the dockable is not currently displayed (or auto-hidden), this method will do nothing. *

the dockable remains registered and can later be shown again at the same * location. * */ public void close(Dockable dockable){ // keep track of where the dockable was DockableState currentState = getDockableState(dockable); if (currentState == null || currentState.isClosed()){// 2006/12/01 return; // no need to continue } int currentStateAsInt = getStateAsInt(currentState); RelativeDockablePosition position = new RelativeDockablePosition(dockingPanel, dockable); DockableState newState = new DockableState(this, dockable, DockableState.STATE_CLOSED, position); DockableStateWillChangeEvent dswe = new DockableStateWillChangeEvent(currentState, newState); DockingActionEvent dae = new DockingActionCloseEvent(this, dockable, currentStateAsInt); if (dockingPanel.isAncestorOf(dockable.getComponent())){ if (isDockingActionAccepted(dae, dswe)){ if (dockable instanceof CompoundDockable){ // V2.1 : propagate closing state to children updateCompoundChildrenState((CompoundDockable)dockable, DockableState.STATE_CLOSED); } remove(dockable); removeFromTabbedGroup(dockable); // 2005/07/13 context.setDockableState(dockable, newState); dockable.getDockKey().setDockableState(DockableState.STATE_CLOSED); fireDockingAction(dae, new DockableStateChangeEvent(currentState, newState)); DockingUtilities.updateResizeWeights(dockingPanel); } } else if (currentState.isHidden()) { if (isDockingActionAccepted(dae, dswe)){ if (dockable instanceof CompoundDockable){ // V2.1 : propagate closing state to children updateCompoundChildrenState((CompoundDockable)dockable, DockableState.STATE_CLOSED); } remove(dockable); removeFromTabbedGroup(dockable); // 2005/07/13 context.setDockableState(dockable, new DockableState(this, dockable, DockableState.STATE_CLOSED, currentState.getPosition())); dockable.getDockKey().setDockableState(DockableState.STATE_CLOSED); fireDockingAction(dae, new DockableStateChangeEvent(currentState, newState)); } } else if (currentState.isFloating()){ if (isDockingActionAccepted(dae, dswe)){ if (dockable instanceof CompoundDockable){ // V2.1 : propagate closing state to children updateCompoundChildrenState((CompoundDockable)dockable, DockableState.STATE_CLOSED); } remove(dockable); removeFromTabbedGroup(dockable); context.setDockableState(dockable, newState); dockable.getDockKey().setDockableState(DockableState.STATE_CLOSED); fireDockingAction(dae, new DockableStateChangeEvent(currentState, newState)); } } else if (currentState.isMaximized()){ // 2006/11/20 restore(dockable); if (getDockableState(dockable).isDocked()){ // ok restore hasn't been vetoed close(dockable); // once again we close, but this time with standard (DOCKED) behaviour } } } /** Iterates through this compound children and properly close them * (without removing them from their parent container) */ private void updateCompoundChildrenState(CompoundDockable cDockable, int state){ ArrayList children = DockingUtilities.findCompoundDockableChildren(cDockable); for (int i=0; i < children.size(); i++){ Dockable d = (Dockable) children.get(i); d.getDockKey().setDockableState(state); DockableState childState = getDockableState(d); DockableState childNewState = new DockableState(this, d, state); context.setDockableState(d, childNewState); context.fireDockableStateChange(new DockableStateChangeEvent(childState, childNewState)); } } /** Convenience method to close all dockables of a TabbedDockableContainer except one. *

* Note : is a dockable is not allowed to close (key.isCloseEnabled() returns false) then it * won't be closed by this method. *

* If the 'exception' dockable isn't contained in a tab, then nothing will happen. */ public void closeAllOtherDockablesInTab(Dockable exception){ TabbedDockableContainer tabContainer = DockingUtilities.findTabbedDockableContainer(exception); if (tabContainer != null){ ArrayList dockables = new ArrayList(tabContainer.getTabCount()-1); for (int i=0; i < tabContainer.getTabCount(); i++){ if (tabContainer.getDockableAt(i) != exception){ dockables.add(tabContainer.getDockableAt(i)); } } for (int i=0; i < dockables.size(); i++){ Dockable d = (Dockable) dockables.get(i); if (d.getDockKey().isCloseEnabled()){ this.close(d); } } } } /** Convenience method to close all dockables of the tabbedContainer * containing "base" (including the base dockable). *

* see also {@link #closeAllOtherDockablesInTab(Dockable)}. *

* Note : is a dockable is not allowed to close (key.isCloseEnabled() returns false) then it * won't be closed by this method. *

* If the 'base' dockable isn't contained in a tab, then nothing will happen. * */ public void closeAllDockablesInTab(Dockable base){ TabbedDockableContainer tabContainer = DockingUtilities.findTabbedDockableContainer(base); if (tabContainer != null){ ArrayList dockables = new ArrayList(tabContainer.getTabCount()); for (int i=0; i < tabContainer.getTabCount(); i++){ dockables.add(tabContainer.getDockableAt(i)); } for (int i=0; i < dockables.size(); i++){ Dockable d = (Dockable) dockables.get(i); if (d.getDockKey().isCloseEnabled()){ this.close(d); } } } } /** Toggles the position of a view between hidden (true) and docked (false). * */ public void setAutoHide(Dockable dockable, boolean hide){ /* setAutoHide is called by user applications (or addHidenDockable() ) and from inside the framework : * - Tab actions (only when in the DOCKED state) * - DockView (listening to DockViewTitleBar property change * - key events from the desktop * - the AutoHideExpandPanel listening to DockViewTitleBar changes * * this method is not used when hiding from FLOATING state, * the "floatingToHide" method is used istead to avoid triggering unused events */ DockKey k = dockable.getDockKey(); DockableState currentState = getDockableState(dockable); int currentStateAsInt = getStateAsInt(currentState); if (hide){ // build a relative position based on the compound container or top container. RelativeDockablePosition position = new RelativeDockablePosition(getRelativeAncestorContainer(dockable), dockable); DockableState newState = new DockableState(this, dockable, DockableState.STATE_HIDDEN, position); DockableStateWillChangeEvent dswe = new DockableStateWillChangeEvent(currentState, newState); DockingActionEvent dae = new DockingActionSimpleStateChangeEvent(this, dockable, currentStateAsInt, DockableState.STATE_HIDDEN); if (currentStateAsInt != DockableState.STATE_HIDDEN && isDockingActionAccepted(dae, dswe)){ AutoHideButton btn = (AutoHideButton) autoHideButtons.get(k); if (btn == null) { btn = new AutoHideButton(); autoHideButtons.put(k, btn); int zone; if (k.getAutoHideBorder() == null) { zone = AutoHidePolicy.getPolicy().getDefaultHideBorder().value(); } else { zone = k.getAutoHideBorder().value(); } btn.init(dockable, zone); borderPanes[zone].setVisible(true); // border may not be visible borderPanes[zone].add(btn); borderPanes[zone].revalidate(); } else { // btn already existing, show it again int zone = btn.getZone(); borderPanes[zone].setVisible(true); // may not be visible btn.setVisible(true); borderPanes[zone].revalidate(); } // now, remove the view from the splitcontainers hide(dockable); context.setDockableState(dockable, newState); k.setDockableState(DockableState.STATE_HIDDEN); fireDockingAction(dae, new DockableStateChangeEvent(currentState, newState)); if (dockable instanceof CompoundDockable){ // V2.1 : also trigger a dockable state change event for compound dockable children updateCompoundChildrenState((CompoundDockable) dockable, DockableState.STATE_HIDDEN); } DockingUtilities.updateResizeWeights(dockingPanel); revalidate(); } } else { // SHOW // remove the button, show again the view DockableState newState = new DockableState(this, dockable, DockableState.STATE_DOCKED); DockableStateWillChangeEvent dswe = new DockableStateWillChangeEvent(currentState, newState); RelativeDockablePosition pos = currentState.getPosition(); Container relativeContainer = pos.getRelativeAncestorContainer(); if (relativeContainer == null){ relativeContainer = dockingPanel; // safety : when a component is loaded from workspace, // we currently loose the container information @todo fix this container in xmlBuildAutoHideNode } DockingActionEvent dae = RelativeDockingUtilities.getInsertionDockingAction( relativeContainer, dockable, currentState, newState); if (! currentState.isDocked() && isDockingActionAccepted(dae, dswe)){ AutoHideButton btn = (AutoHideButton) autoHideButtons.get(k); assert btn != null; int zone = btn.getZone(); btn.setVisible(false); expandPanel.collapse(); if (borderPanes[zone].getVisibleButtonCount() == 0){ // hide button panel if no more buttons (to avoid a remaining visible border) borderPanes[zone].setVisible(false); revalidate(); } expandPanel.remove(dockable); show(dockable, dae); context.setDockableState(dockable, newState); k.setDockableState(DockableState.STATE_DOCKED); fireDockingAction(dae, new DockableStateChangeEvent(currentState, newState)); if (dockable instanceof CompoundDockable){ // V2.1 : also trigger a dockable state change event for compound dockable children updateCompoundChildrenState((CompoundDockable) dockable, DockableState.STATE_DOCKED); } DockingUtilities.updateResizeWeights(dockingPanel); revalidate(); } } } /** hide the view (used with autohide features) */ private void hide(Dockable dockable) { if (dockable == null){ throw new NullPointerException("dockable"); } DockableContainer dockableContainer = DockingUtilities. findSingleDockableContainer(dockable); if (dockableContainer == null){// || !dockingPanel.isAncestorOf((Component) dockableContainer)){ throw new IllegalArgumentException("not docked"); } remove(dockable); } /** recalculates and returns the insets taken by autoexpand * borders around the docking panel. * */ public Insets getDockingPanelInsets() { // recalculate the location and size of the mouse grabber Insets i = new Insets(0, 0, 0, 0); if (topBorderPane != null && topBorderPane.isVisible()) { i.top += topBorderPane.getHeight(); } if (leftBorderPane != null && leftBorderPane.isVisible()) { i.left += leftBorderPane.getWidth(); } if (bottomBorderPane != null && bottomBorderPane.isVisible()) { i.bottom += bottomBorderPane.getHeight(); } if (rightBorderPane != null && rightBorderPane.isVisible()) { i.right += rightBorderPane.getWidth(); } return i; } /** Creates and returns an array of all registered dockable with their current * state. *

* Visibility states are [DockableState.STATE_CLOSED, STATE_DOCKED, STATE_HIDDEN] * @return an array of DockableState */ public DockableState[] getDockables(){ return context.getDockables(); } /** Installs multiple drag sources. * @see #installDockableDragSource(DockableDragSource) * * */ public void installDockableDragSources(DockableDragSource[] sources){ if (sources != null){ for (int i = 0; i < sources.length; i++) { installDockableDragSource(sources[i]); } } } /** Uninstalls multiple drag sources. *@see #uninstallDockableDragSource(DockableDragSource) * * */ public void uninstallDockableDragSources(DockableDragSource[] sources){ if (sources != null){ for (int i = 0; i < sources.length; i++) { uninstallDockableDragSource(sources[i]); } } } /** This method is used by DockableContainers in order to register their * DockableDragSource(s) to the DragControler. *

* Adds a MouseListener and a MouseMotionListener to the * Component-DockableDragSource source. These listeners * are used to perform start-dragging-docking actions over the source component */ public void installDockableDragSource(DockableDragSource source) { ((Component)source).addMouseListener(dragControler); ((Component)source).addMouseMotionListener(dragControler); } /** This method is used by DockableContainers in order to unregister their * DockableDragSource(s) to the DragControler. *

* Removes the MouseListener and MouseMotionListener added on installDockableDragSource() * * @see #installDockableDragSource(DockableDragSource) * */ public void uninstallDockableDragSource(DockableDragSource source) { ((Component)source).removeMouseListener(dragControler); ((Component)source).removeMouseMotionListener(dragControler); } /** Request this desktop to reset it's contained views to their preferred size, if * possible. *

* This method should be invoked when the component is realized (visible) due * to Split Panes implementation. * */ public void resetToPreferredSize() { dockingPanel.resetToPreferredSize(); } /** Saves the current desktop configuration into an XML stream. *

* The stream is not closed at the end of the operation. *

* As of version 2.1, this method delegates the work to DockingContext.writeXML, which * will export every dekstop sharing the same context (and not only this one) * * @see #readXML(InputStream) * */ public void writeXML(OutputStream stream) throws IOException { context.writeXML(stream); // will call back writeDesktopXML for each desktop } /* package protected for callback from DockingContext */ void writeDesktopNode(PrintWriter out) throws IOException { out.println(""); out.println(""); if (dockingPanel.getComponentCount() > 0){ // only one top component (DockableContainer or SplitContainer) xmlWriteComponent(dockingPanel.getComponent(0), out); } Dockable max = getMaximizedDockable(); // 2007/01/08 if ( max != null){ out.println(""); DockKey key = max.getDockKey(); out.println(""); out.println(""); } out.println(""); for (int i = 0; i < borderPanes.length; i++) { xmlWriteBorder(borderPanes[i], out); } // finish with the floating dockables xmlWriteFloating(out); // and the tab groups xmlWriteTabGroups(out); out.println(""); } private void xmlWriteBorder(AutoHideButtonPanel borderPanel, PrintWriter out) throws IOException { if (borderPanel.isVisible()){ out.println(""); Component[] comps = borderPanel.getComponents(); for (int i = 0; i < comps.length; i++) { if (comps[i] instanceof AutoHideButton) { xmlWriteBorderDockable(((AutoHideButton)comps[i]), out); } } out.println(""); } } private void xmlWriteFloating(PrintWriter out) throws IOException { // there is no list of floating : we have to fetch the dockable states // updated : we also need to store grouping information ArrayList processedDockables = new ArrayList(); Window desktopWindow = SwingUtilities.getWindowAncestor(this); Point windowLocation; if (desktopWindow != null){ windowLocation = desktopWindow.getLocation(); } else { windowLocation = new Point(); // fail safe } ArrayList floatingDockables = context.getDockablesByState(this, DockableState.STATE_FLOATING); for (int i=0; i < floatingDockables.size(); i++){ Dockable d = (Dockable) floatingDockables.get(i); //DockableState state = (DockableState)floatingDockables.get(i); // Dockable d = (Dockable) state.getDockable(); if (processedDockables.contains(d)){ continue; // ignore this dockable : already processed } Window w = SwingUtilities.getWindowAncestor(d.getComponent()); Rectangle r = w.getBounds(); out.println(""); TabbedDockableContainer tabContainer = DockingUtilities.findTabbedDockableContainer(d); if (tabContainer != null){ // fetch all the dockables of this container for (int t=0; t < tabContainer.getTabCount(); t++){ Dockable tabDockable = tabContainer.getDockableAt(t); processedDockables.add(tabDockable); xmlWriteFloatingDockable(tabDockable, out); } } else { // single floating processedDockables.add(d); xmlWriteFloatingDockable(d, out); } out.println(""); } } private void xmlWriteComponent(Component comp, PrintWriter out) throws IOException { if (comp instanceof SplitContainer){ xmlWriteSplit((SplitContainer) comp, out); } else if (comp instanceof TabbedDockableContainer){ xmlWriteTab((TabbedDockableContainer)comp, out); } else if (comp instanceof SingleDockableContainer){ Dockable d = ((SingleDockableContainer)comp).getDockable(); xmlWriteDockable(d, out); } else if (comp == dummyMaximedReplacer){ //2006/12/01 (maximized component wasn't saved) SingleDockableContainer maxContainer = (SingleDockableContainer)maximizedComponent; Dockable d = maxContainer.getDockable(); xmlWriteDockable(d, out); } } private void xmlWriteTab(TabbedDockableContainer tpane, PrintWriter out) throws IOException { out.println(""); for (int i = 0; i < tpane.getTabCount(); i++) { xmlWriteDockable(tpane.getDockableAt(i), out); } out.println(""); } private void xmlWriteDockable(Dockable dockable, PrintWriter out) throws IOException { boolean isCompound = dockable instanceof CompoundDockable; if (isCompound){ out.println(""); } else { out.println(""); } DockKey key = dockable.getDockKey(); out.println(""); if (isCompound){ CompoundDockable d = (CompoundDockable)dockable; CompoundDockingPanel cdp = (CompoundDockingPanel) d.getComponent(); // no choice here if (cdp.getComponentCount() > 0){ // compound panels cannont have more than one child (split/tab/single) Component child = cdp.getComponent(0); xmlWriteComponent(child, out); } } out.println(""); } private void xmlWriteCompoundDockable(CompoundDockable dockable, PrintWriter out) throws IOException { out.println(""); DockKey key = dockable.getDockKey(); out.println(""); CompoundDockingPanel cdp = (CompoundDockingPanel) dockable.getComponent(); // no choice here if (cdp.getComponentCount() > 0){ // compound panels cannont have more than one child (split/tab/single) Component child = cdp.getComponent(0); xmlWriteComponent(child, out); } out.println(""); } private void xmlWriteBorderDockable(AutoHideButton btn, PrintWriter out) throws IOException { if (btn.isVisible()){ Dockable dockable = btn.getDockable(); xmlWriteDockableWithRelativePosition(dockable, out); } } private void xmlWriteDockableWithRelativePosition(Dockable dockable, PrintWriter out) throws IOException { DockableState state = context.getDockableState(dockable); RelativeDockablePosition position = (RelativeDockablePosition) state.getPosition(); boolean isCompound = dockable instanceof CompoundDockable; if (isCompound){ out.println(""); } else { out.println(""); } DockKey key = dockable.getDockKey(); out.println(""); out.println(""); if (isCompound){ CompoundDockable d = (CompoundDockable)dockable; CompoundDockingPanel cdp = (CompoundDockingPanel) d.getComponent(); // no choice here if (cdp.getComponentCount() > 0){ // compound panels cannont have more than one child (split/tab/single) Component child = cdp.getComponent(0); xmlWriteComponent(child, out); } } out.println(""); } private void xmlWriteCompoundDockableWithRelativePosition(CompoundDockable dockable, PrintWriter out) { /* The autohide component is a compound dockable : we'll have to save its position then traverse its children */ DockableState state = context.getDockableState(dockable); RelativeDockablePosition position = (RelativeDockablePosition) state.getPosition(); DockKey key = dockable.getDockKey(); out.println(""); out.println(""); out.println(""); } private void xmlWriteFloatingDockable(Dockable dockable, PrintWriter out) throws IOException{ DockableState state = context.getDockableState(dockable); RelativeDockablePosition position = (RelativeDockablePosition) state.getPosition(); boolean isCompound = dockable instanceof CompoundDockable; if (isCompound){ out.println(""); } else { out.println(""); } DockKey key = dockable.getDockKey(); out.println(""); out.println(""); DockableState prev = (DockableState) previousFloatingDockableStates.get(dockable); out.println(""); if (isCompound){ CompoundDockable d = (CompoundDockable)dockable; CompoundDockingPanel cdp = (CompoundDockingPanel) d.getComponent(); // no choice here if (cdp.getComponentCount() > 0){ // compound panels cannont have more than one child (split/tab/single) Component child = cdp.getComponent(0); xmlWriteComponent(child, out); } } out.println(""); } private void xmlWriteSplit(SplitContainer split, PrintWriter out) throws IOException { double location; if (split.getOrientation() == JSplitPane.HORIZONTAL_SPLIT){ location = split.getLeftComponent().getWidth() / (double)(split.getWidth() - split.getDividerSize()); // 2006/09/25 } else { location = split.getTopComponent().getHeight() / (double)(split.getHeight() - split.getDividerSize()); } out.println(""); xmlWriteComponent(split.getLeftComponent(), out); xmlWriteComponent(split.getRightComponent(), out); out.println(""); } /** TabGroups are the memory of tabs (even for hidden or floating dockables) used to * put them back on the right tab when docked again */ private void xmlWriteTabGroups(PrintWriter out) throws IOException { // there is redundant information in the tabbedGroups Map... so we have to simplify it ArrayList uniqueGroups = new ArrayList(); ArrayList processedDockables = new ArrayList(); Iterator it = tabbedGroups.keySet().iterator(); while (it.hasNext()){ Dockable d = (Dockable) it.next(); if (! processedDockables.contains(d)){ processedDockables.add(d); LinkedList tabList = (LinkedList) tabbedGroups.get(d); Iterator listIt = tabList.iterator(); while (listIt.hasNext()){ Dockable d2 = (Dockable) listIt.next(); if (!processedDockables.contains(d2)){ processedDockables.add(d2); } } uniqueGroups.add(tabList); } } out.println(""); for (int i = 0; i < uniqueGroups.size(); i++) { out.println(""); LinkedList group = (LinkedList) uniqueGroups.get(i); Iterator listIt = group.iterator(); while (listIt.hasNext()) { Dockable d = (Dockable) listIt.next(); xmlWriteDockableTab(d, out); } out.println(""); } out.println(""); } private void xmlWriteDockableTab(Dockable dockable, PrintWriter out) throws IOException { out.println(""); DockKey key = dockable.getDockKey(); out.println(""); out.println(""); } /** Reads an XML encoded stream as the new desktop configuration. *

* When the method returns, the desktop is totally reconfigured with posiibly different * dockable at different positions. *

* Note : The DockKeys of the stream must be registered with * the {@link #registerDockable(Dockable) registerDockable} method, * prior readXML.
* This is the case if the desktop is already open and dockables * laid out, but might not be the case if this method is used at application startup * to populate an empty desktop. * *

* Dismisses all visible dockables (docked and auto-hidden), and clear their DockableState. *

* The stream is not closed at the end of the operation. * @see #writeXML(OutputStream) * @see #registerDockable(Dockable) * */ public void readXML(InputStream in) throws ParserConfigurationException, IOException, SAXException { context.readXML(in); } /** removes every dockables from this desktop */ public void clear(){ dockingPanel.removeAll(); for (int i = 0; i < borderPanes.length; i++) { borderPanes[i].removeAll(); borderPanes[i].setVisible(false); } boolean wasHeavyMaximized = false; if (maximizedComponent != null){ // clean up maximization state if (DockingPreferences.isLightWeightUsageEnabled()){ remove(maximizedComponent); // remove the single dockable container } else { remove(maximizedComponent.getParent()); // remove the awt panel wasHeavyMaximized = true; } maximizedComponent = null; // 2006/11/20 ooops ! } autoHideButtons.clear(); expandPanel.collapse(); expandPanel.clear(); previousFloatingDockableStates.clear(); tabbedGroups.clear(); // clear the floatables windows ArrayList floatingDockables = context.getDockablesByState(this, DockableState.STATE_FLOATING); for (int i=0; i < floatingDockables.size(); i++){ Dockable d = (Dockable) floatingDockables.get(i); remove(d); } } /* package protected */ void readDesktopNode(Element desktopElement) throws SAXException { /* called back by DockingContext to read (and install) a desktop configuration from an xml stream */ NodeList children = desktopElement.getChildNodes(); for (int i = 0, len = children.getLength(); i < len; i++) { Node child = children.item(i); xmlBuildRootNode(child); } DockingUtilities.updateResizeWeights(dockingPanel); // 2006/12/01 revalidate(); } private void xmlBuildRootNode(Node node) throws SAXException{ if (node.getNodeType() == Node.ELEMENT_NODE){ Element elt = (Element) node; String name = elt.getNodeName(); if (name.equals("DockingPanel")){ // only one child at most NodeList children = elt.getChildNodes(); for (int i = 0, len = children.getLength(); i < len; i++) { xmlBuildDockingPanelNode(elt.getChildNodes().item(i)); } } else if (name.equals("Border")){ int zone = Integer.parseInt(elt.getAttribute("zone")); AutoHideButtonPanel borderPanel = borderPanes[zone]; borderPanel.setVisible(true); // border may not be visible NodeList children = elt.getElementsByTagName("Dockable"); for (int i = 0, len = children.getLength(); i < len; i++) { xmlBuildAutoHideNode(borderPanel, (Element)children.item(i)); } borderPanel.revalidate(); } else if (name.equals("Floating")){ int x = Integer.parseInt(elt.getAttribute("x")); int y = Integer.parseInt(elt.getAttribute("y")); int width = Integer.parseInt(elt.getAttribute("width")); int height = Integer.parseInt(elt.getAttribute("height")); NodeList children = elt.getElementsByTagName("Dockable"); xmlBuildFloatingNode(children, new Rectangle(x, y, width, height)); //2005/10/10 /* for (int i = 0, len = children.getLength(); i < len; i++) { xmlBuildFloatingNode((Element)children.item(i), new Rectangle(x, y, width, height)); }*/ } else if (name.equals("TabGroups")){ NodeList children = elt.getElementsByTagName("TabGroup"); xmlBuildTabGroup(children); //2005/10/10 } else { throw new SAXNotRecognizedException(name); } } } private void xmlBuildAutoHideNode(AutoHideButtonPanel borderPanel, Element dockableElt) throws SAXException { Element hideElt = (Element)dockableElt.getElementsByTagName("RelativePosition").item(0); float x = Float.parseFloat(hideElt.getAttribute("x")); float y = Float.parseFloat(hideElt.getAttribute("y")); float w = Float.parseFloat(hideElt.getAttribute("w")); float h = Float.parseFloat(hideElt.getAttribute("h")); RelativeDockablePosition position = new RelativeDockablePosition(x, y, w, h); AutoHideButton btn = new AutoHideButton(); Dockable dockable = xmlGetDockable(dockableElt); autoHideButtons.put(dockable.getDockKey(), btn); context.setDockableState(dockable, new DockableState(this, dockable, DockableState.STATE_HIDDEN, position)); dockable.getDockKey().setDockableState(DockableState.STATE_HIDDEN); btn.init(dockable, borderPanel.getBorderZone()); borderPanel.add(btn); if (dockable instanceof CompoundDockable){ // check for children and build them xmlBuildCompoundDockable((CompoundDockable) dockable, dockableElt, DockableState.STATE_HIDDEN); } } /* private void xmlBuildFloatingNode(Element dockableElt, Rectangle bounds) { */ private void xmlBuildFloatingNode(NodeList dockables, Rectangle bounds) throws SAXException { // @todo not optimal.. we should refactor it oustide this method Window desktopWindow = SwingUtilities.getWindowAncestor(this); if (desktopWindow != null){ Point windowLocation = desktopWindow.getLocation(); bounds.x += windowLocation.x; // position is relative bounds.y += windowLocation.y; } //JDialog dialog = null; FloatingDockableContainer fdc = null; TabbedDockableContainer tdc = null; if (dockables.getLength()>1){ // it's a floating tab tdc = DockableContainerFactory.getFactory().createTabbedDockableContainer(); tdc.installDocking(this); ((JTabbedPane) tdc).addChangeListener(focusHandler); // our best way to track selection (focus) changes } Dockable baseDockable = null; // used when there are tabs for (int i=0; i < dockables.getLength(); i++){ Element dockableElt = (Element) dockables.item(i); Element hideElt = (Element)dockableElt.getElementsByTagName("RelativePosition").item(0); float x = Float.parseFloat(hideElt.getAttribute("x")); float y = Float.parseFloat(hideElt.getAttribute("y")); float w = Float.parseFloat(hideElt.getAttribute("w")); float h = Float.parseFloat(hideElt.getAttribute("h")); RelativeDockablePosition position = new RelativeDockablePosition(dockingPanel, x, y, w, h); Dockable dockable = xmlGetDockable(dockableElt); if (i == 0){ baseDockable = dockable; } Element previousState = (Element)dockableElt.getElementsByTagName("PreviousState").item(0); int istate = Integer.parseInt(previousState.getAttribute("state")); DockableState state = new DockableState(this, dockable, istate, position); storePreviousFloatingState(dockable, state); if (fdc == null){ //if (dialog == null}){ // dialog = (JDialog) createFloatingDockableContainer(dockable); fdc = createFloatingDockableContainer(dockable); } else { // add as a tab if (tdc.getTabCount() == 0){ // first tab : replace the current DetachedDockView by the tab container // not very efficient... @todo : sort this out DockableContainer base = DockingUtilities.findDockableContainer(baseDockable); DockingUtilities.replaceChild(((Component)base).getParent(), (Component)base, (Component)tdc); tdc.addDockable(baseDockable, 0); } tdc.addDockable(dockable, tdc.getTabCount()); } context.setDockableState(dockable, new DockableState(this, dockable, DockableState.STATE_FLOATING, position)); dockable.getDockKey().setDockableState(DockableState.STATE_FLOATING); if (dockable instanceof CompoundDockable){ // check for children and build them xmlBuildCompoundDockable((CompoundDockable) dockable, dockableElt, DockableState.STATE_FLOATING); } } DockingUtilities.setBounds(fdc, bounds); //dialog.setBounds(bounds); //dialog.validate(); //dialog.setVisible(true); DockingUtilities.validate(fdc); DockingUtilities.setVisible(fdc, true); } private void xmlBuildDockingPanelNode(Node node) throws SAXException { if (node.getNodeType() == Node.ELEMENT_NODE){ Component comp = xmlCreateComponent((Element) node, DockableState.STATE_DOCKED); if (comp != null){ dockingPanel.add(comp, BorderLayout.CENTER); } } } private Component xmlCreateComponent(Element elt, int dockableState) throws SAXException { if (elt.getNodeName().equals("Split")){ SplitContainer split = xmlBuildSplitContainer(elt, dockableState); return split; } else if (elt.getNodeName().equals("Dockable")){ Dockable d = xmlGetDockable(elt); SingleDockableContainer sdc = DockableContainerFactory.getFactory() .createDockableContainer(d, DockableContainerFactory.PARENT_SPLIT_CONTAINER); context.setDockableState(d, new DockableState(this, d, dockableState)); d.getDockKey().setDockableState(dockableState); sdc.installDocking(this); if (d instanceof CompoundDockable){ // check for children and build them xmlBuildCompoundDockable((CompoundDockable) d, elt, dockableState); } return (Component) sdc; } else if (elt.getNodeName().equals("TabbedDockable")){ TabbedDockableContainer tdc = xmlBuildTabbedDockableContainer(elt, dockableState); return (Component) tdc; } else if (elt.getNodeName().equals("MaximizedDockable")){ // this should be the last element from DockingPanel node Dockable d = xmlGetDockable(elt); maximize(d); return null; } else { throw new SAXNotRecognizedException(elt.getNodeName()); } } private void xmlBuildCompoundDockable(CompoundDockable dockable, Element compoundElt, int dockableState) throws SAXException{ /* a compound dockable can hold a sub dockable (or split/tabs) */ CompoundDockingPanel compoundPanel = (CompoundDockingPanel) dockable.getComponent(); compoundPanel.removeAll(); // cleanup the compound at every workspace reloading 2007/01/08 NodeList children = compoundElt.getChildNodes(); for (int i = 0, len = children.getLength(); i < len; i++) { Node node = children.item(i); if (node.getNodeType() == Node.ELEMENT_NODE){ Element elt = (Element) node; if (elt.getNodeName().equals("Key")){ // ignore : it's the key of the compound dockable } else { Component comp = xmlCreateComponent(elt, dockableState); compoundPanel.add(comp, BorderLayout.CENTER); return; // no more than a single child } } } } private SplitContainer xmlBuildSplitContainer(Node node, int dockableState) throws SAXException{ Element elt = (Element) node; int orientation = Integer.parseInt(elt.getAttribute("orientation")); String loc = elt.getAttribute("location"); double location = 0.5; if (loc != null && !loc.equals("")){ location = Double.parseDouble(loc); } SplitContainer split = new SplitContainer(orientation); split.setDividerLocation(location); boolean left = true; for (int i = 0; i < node.getChildNodes().getLength(); i++) { Node child = node.getChildNodes().item(i); if (child.getNodeType() == Node.ELEMENT_NODE){ Component comp = xmlCreateComponent((Element)child, dockableState); if (left){ split.setLeftComponent(comp); left = false; } else { split.setRightComponent(comp); } } } return split; } private TabbedDockableContainer xmlBuildTabbedDockableContainer(Element elt, int dockableState) throws SAXException { TabbedDockableContainer tdc = DockableContainerFactory.getFactory().createTabbedDockableContainer(); tdc.installDocking(this); ((JTabbedPane) tdc).addChangeListener(focusHandler); // our best way to track selection (focus) changes Dockable base = null; for (int i = 0; i < elt.getChildNodes().getLength(); i++) { Node child = elt.getChildNodes().item(i); if (child.getNodeType() == Node.ELEMENT_NODE){ Dockable d = xmlGetDockable((Element) child); if (base == null){ base = d; } context.setDockableState(d, new DockableState(this, d, dockableState)); d.getDockKey().setDockableState(dockableState); tdc.addDockable(d, tdc.getTabCount()); // update the tab group if (base != d){ addToTabbedGroup(base, d); } if (d instanceof CompoundDockable){ // check for children and build them is needed xmlBuildCompoundDockable((CompoundDockable) d, (Element) child, dockableState); } } } return tdc; } private Dockable xmlGetDockable(Element dockableElt) { Element key = (Element)dockableElt.getElementsByTagName("Key").item(0); String name = key.getAttribute("dockName"); Dockable dockable = context.getDockableByKey(name); if (dockable == null){ throw new NullPointerException("Dockable " + name + " not registered"); } return dockable; } /** rebuild the tabbedGroups structure (memory of tabbed dockables) */ private void xmlBuildTabGroup(NodeList group) { // this pass is useful for hidden dockable that need to be reassociated // with their tab group. // (tabbed dockable don't need it as this information is implicit (during xml tab creation) for (int i=0; i < group.getLength(); i++){ Element groupElt = (Element)group.item(i); NodeList dockables = groupElt.getElementsByTagName("Dockable"); Dockable base = null; for (int j=0; j < dockables.getLength(); j++){ Element dockableElt = (Element)dockables.item(j); Dockable d = xmlGetDockable(dockableElt); if (j == 0){ base = d; } else { addToTabbedGroup(base, d); } } } } /** Adds a dockable in the docking desktop. *

* This method can be used mainly in two situations : *

    *
  • the desktop is empty (when not empty, you can use split() or createTab() to * add a dockable relatively to another) *
  • the dockable is currently closed, and it must be shown again *
  • note that if the desktop is not empty, the dockable will be added in the bottom * of the desktop (equivalent to addDockable(dockable 0,0.8,1,0.2)). *
*/ public void addDockable(Dockable dockable) { /* addDockable isn't called internally by the API : just for user applications */ addDockable(dockable, new RelativeDockablePosition(0,0.8,0.5,0.2)); } /** Adds a dockable in the docking desktop, and tries to respect the relative * positionning provided. *

* This method is used to reposition a closed dockable at its previous location * on the desktop. As it relies on the Component.findComponentAt(Point) method , * the desktop must already be visible. * *

* The preferred way to obtain a particular visual docking confuguration is to * use a combination of add(), split() and createTab() methods, as these methods do * not rely on an interpretation (and approximation) of constraints. * *

* Precision of constraints : as the docking management is based on a mix of * horizontal and vertical splitting zones, it is not always possible to * respect the constraints given. *

* The current implementation will do the following : *

    *
  • find the splitter containing the given center (x + width/2, y + height/2) of the dockable *
  • try to respect the x and y, constraints. *
  • try to respect the width and height constraints. *
  • sub-split the splitter (horizontally or vertically) zone and position * the Dockable in the most appropriate zone (top, left, bottom, right). *
* * @param dockable the dockable to add (must not be already visible) * @param position relative position of the dockable * * @throws IllegalArgumentException if the dockable already belongs to the desktop containment * hierarchy. */ public void addDockable(Dockable dockable, RelativeDockablePosition position){ /* addDockable isn't called internally by the API : just for user applications */ if (this.isAncestorOf(dockable.getComponent())){ throw new IllegalArgumentException("Dockable is already contained in the desktop"); } registerDockable(dockable); if (DockingUtilities.findSingleDockableContainer(dockable) != null){ remove(dockable); } DockableState newState = new DockableState(this, dockable, DockableState.STATE_DOCKED, position); DockableState currentState = getDockableState(dockable); int currentStateAsInt = getStateAsInt(currentState); DockableStateWillChangeEvent dswe = new DockableStateWillChangeEvent(currentState, newState); DockingActionEvent dae = new DockingActionAddDockableEvent(this, dockable, currentStateAsInt, newState.getState(), dockingPanel); if (isDockingActionAccepted(dae, dswe)){ SingleDockableContainer sdc = RelativeDockingUtilities.insertDockable( dockingPanel, dockable, position); sdc.installDocking(this); context.setDockableState(dockable, newState); dockable.getDockKey().setDockableState(DockableState.STATE_DOCKED); DockableStateChangeEvent dse = new DockableStateChangeEvent(currentState, newState); fireDockingAction(dae, dse); DockingUtilities.updateResizeWeights(dockingPanel); } } /** Replaces a dockable by another one. *

* Useful for example to reserve some space on a desktop by using a "placeholder' when * other dockables aren't visible (Multiple Tabbed Document Interface with always a dockable * visible even when no document is loaded). *

* Implementation note : this method assumes only the "base" dockable is visible (the replacer must be * in the CLOSED state). It also assumes the base dockable isn't a compound dockable. These limitations * will be removed in a later release. * *

* There is currently no DnD gesture associated to this action (although the * "HotSwap" gesture would be a good candidate). So this method currently doesn't trigger any event * (state change, action), yet it could change later. * * @since 2.1 * @throws IllegalArgumentException when dockables aren't in the appropriate state or hierarchy. */ public void replace(Dockable base, Dockable replacer){ DockableState baseState = context.getDockableState(base); DockableState replacerState = context.getDockableState(replacer); DockableState newBaseState = new DockableState(replacerState.getDesktop(), base, replacerState.getState()); DockableState newReplacerState = new DockableState(baseState.getDesktop(), replacer, baseState.getState()); TabbedDockableContainer tdcBase = DockingUtilities.findTabbedDockableContainer(base); if (!replacerState.isClosed()){ throw new IllegalArgumentException("replacer isn't closed"); } if (base instanceof CompoundDockable){ throw new IllegalArgumentException("base cannot be a compound dockable"); } if (tdcBase != null){ int iBase = tdcBase.indexOfDockable(base); tdcBase.removeDockable(base); tdcBase.addDockable(replacer, iBase); } else { SingleDockableContainer sdcBase = DockingUtilities.findSingleDockableContainer(base); Container sdcBaseParent = ((Component)sdcBase).getParent(); if (sdcBaseParent instanceof SplitContainer){ SplitContainer split = (SplitContainer) sdcBaseParent; boolean isLeft = split.getLeftComponent() == sdcBase; SingleDockableContainer sdc = DockableContainerFactory.getFactory().createDockableContainer( replacer, DockableContainerFactory.PARENT_SPLIT_CONTAINER); sdc.installDocking(this); if (isLeft){ split.setLeftComponent((Component)sdc); } else { split.setRightComponent((Component)sdc); } split.revalidate(); } else if (sdcBaseParent instanceof DockingPanel){ // a single component DockingPanel dp = (DockingPanel)sdcBaseParent; dp.remove(0); SingleDockableContainer sdc = DockableContainerFactory.getFactory().createDockableContainer( replacer, DockableContainerFactory.PARENT_SPLIT_CONTAINER); sdc.installDocking(this); dp.add((Component) sdc, BorderLayout.CENTER); dp.revalidate(); } else if (sdcBaseParent instanceof CompoundDockingPanel){ // a single component CompoundDockingPanel cdp = (CompoundDockingPanel)sdcBaseParent; cdp.remove(0); SingleDockableContainer sdc = DockableContainerFactory.getFactory().createDockableContainer( replacer, DockableContainerFactory.PARENT_SPLIT_CONTAINER); sdc.installDocking(this); cdp.add((Component) sdc, BorderLayout.CENTER); cdp.revalidate(); } else { throw new RuntimeException("Wrong container hierarchy : " + sdcBaseParent); } } // swap states context.setDockableState(base, newBaseState); context.setDockableState(replacer, newReplacerState); } /* small utility method to avoid bloating code everywhere (return a default state value if state object is null) */ private static int getStateAsInt(DockableState state){ if (state == null){ return DockableState.STATE_CLOSED; } else { return state.getState(); } } /** Adds a dockable inside a compound dockable. *

* This is the method to start a nesting hierarchy inside a compound dockable * (once the first dockable is added, you add subsequent dockables with standard split/createTab methods) *

    *
  • note that if the compound dockable is not empty, this method will raise an exception. *
* @since 2.1 */ public void addDockable(CompoundDockable base, Dockable dockable) { registerDockable(dockable); DockableState currentState = getDockableState(dockable); int currentStateAsInt = getStateAsInt(currentState); DockableState newState = new DockableState(this, dockable, DockableState.STATE_DOCKED); DockableStateWillChangeEvent dswe = new DockableStateWillChangeEvent(currentState, newState); CompoundDockingPanel panel = (CompoundDockingPanel) base.getComponent(); DockingActionEvent dae = new DockingActionAddDockableEvent(this, dockable, currentStateAsInt, newState.getState(), panel); if (isDockingActionAccepted(dae, dswe)){ DockableContainer dockableContainer = DockableContainerFactory.getFactory(). createDockableContainer(dockable, DockableContainerFactory.PARENT_DESKTOP); dockableContainer.installDocking(this); //TODO : check and raise exception if not empty panel.add((JComponent)dockableContainer, BorderLayout.CENTER); context.setDockableState(dockable, newState); dockable.getDockKey().setDockableState(DockableState.STATE_DOCKED); fireDockingAction(dae, new DockableStateChangeEvent(currentState, newState)); } } /** Evaluates and returns the preferred size of the desktop, according to * its contents and auto-hide borders.*/ public Dimension getPreferredSize(){ Insets i = getDockingPanelInsets(); Dimension dim = dockingPanel.getPreferredSize(); dim.width += i.left + i.right; dim.height += i.top + i.bottom; return dim; } /** Adds a new DockableStateChangeListener to this desktop. *

* DockableStateChange Events are triggered after the state change. * *

As of version 2.0 of the framework, this method can also be replaced by * adding a propertychangeListener on the DockKey object (and react to its DockableState * property). * * */ public void addDockableStateChangeListener(DockableStateChangeListener listener){ context.addDockableStateChangeListener(listener); } /** Removes a DockableStateChangeListener from this desktop. * */ public void removeDockableStateChangeListener(DockableStateChangeListener listener){ context.removeDockableStateChangeListener(listener); } /** Adds a new DockableStateWillChangeListener to this desktop. *

* DockableStateWillChange Events are triggered before the state change, and * are vetoable. * */ public void addDockableStateWillChangeListener(DockableStateWillChangeListener listener){ context.addDockableStateWillChangeListener(listener); } /** Removes a DockableStateWillChangeListener from this desktop. * */ public void removeDockableStateWillChangeListener(DockableStateWillChangeListener listener){ context.removeDockableStateWillChangeListener(listener); } /** Adds a new DockingActionListener to this desktop. *

* DockingAction Events are triggered before and after any docking action (split, tab, close, hide...) and * allow for precise tracking (and vetoing) of these operations. * * @see #removeDockingActionListener(DockingActionListener) */ public void addDockingActionListener(DockingActionListener listener){ context.addDockingActionListener(listener); } /** Removes a DockingActionListener from this desktop. * * @see #addDockingActionListener(DockingActionListener) */ public void removeDockingActionListener(DockingActionListener listener){ context.removeDockingActionListener(listener); } /** Adds a new DockableSelectionListener to this desktop. *

* DockableSelection Events are triggered when a dockable takes the focus. * */ public void addDockableSelectionListener(DockableSelectionListener listener){ context.addDockableSelectionListener(listener); } /** Removes a DockableSelectionListener from this desktop. * */ public void removeDockableSelectionListener(DockableSelectionListener listener){ context.removeDockableSelectionListener(listener); } /** Registers and add a dockable on an auto-hide border. *

this method should be called at startup time (when the dockable isn't yet * displayed). to toggle a dockable from docked to auto-hide, please use * setAutoHide(Dockable, boolean) instead. * *

However, this method will not fail if the dockable is already displayed : * in that case, it will delegate autohide to setAutoHide(Dockable, boolean), thus * dropping the dockedPosition argument. * * @param dockable the dockable to add (to select the border where the dockable * will be positionned, use the DockKey.setAutoHideBorder mehod * * @param dockedPosition relative positionning (may be null) indicating where to * dock the dockable when leaving its auto-hide border. * */ public void addHiddenDockable(Dockable dockable, RelativeDockablePosition dockedPosition){ /* not used from inside the API : only for user applications */ DockableState currentState = getDockableState(dockable); // should be null if (currentState != null && !currentState.isHidden()){ // delegate autohide to the right method setAutoHide(dockable, true); return; } registerDockable(dockable); currentState = getDockableState(dockable); // now should be CLOSED int currentStateAsInt = getStateAsInt(currentState); DockableState newState = new DockableState(this, dockable, DockableState.STATE_HIDDEN, dockedPosition); DockableStateWillChangeEvent dswe = new DockableStateWillChangeEvent(currentState, newState); DockingActionEvent dae = new DockingActionSimpleStateChangeEvent(this, dockable, currentStateAsInt, DockableState.STATE_HIDDEN); DockKey k = dockable.getDockKey(); if (currentStateAsInt != DockableState.STATE_HIDDEN && isDockingActionAccepted(dae, dswe)){ AutoHideButton btn = (AutoHideButton) autoHideButtons.get(k); if (btn == null) { btn = new AutoHideButton(); autoHideButtons.put(k, btn); int zone; if (k.getAutoHideBorder() == null) { zone = AutoHidePolicy.getPolicy().getDefaultHideBorder().value(); } else { zone = k.getAutoHideBorder().value(); } btn.init(dockable, zone); borderPanes[zone].setVisible(true); // border may not be visible borderPanes[zone].add(btn); borderPanes[zone].revalidate(); } else { // btn already existing, show it again int zone = btn.getZone(); borderPanes[zone].setVisible(true); // may not be visible btn.setVisible(true); borderPanes[zone].revalidate(); } context.setDockableState(dockable, newState); dockable.getDockKey().setDockableState(DockableState.STATE_HIDDEN); fireDockingAction(dae, new DockableStateChangeEvent(currentState, newState)); revalidate(); } } /** Changes the width of a dockable (the dockable must already be visible). * *

* Note that this method works by modifying the divider location of the * nearest SplitContainer ancestor of the dockable (the first splitted horizontally). * *

* As this method must be called when the desktop is visible, a simple way to * do this is to add a window listener to the parent frame of the desktop, and call this * method from the windowOpened(WindowEvent) notification. * * @param width new width (if between 0 and 1, width is taken as a proportional width, * otherwise it is a pixel width. * * */ public void setDockableWidth(Dockable dockable, double width){ SplitContainer split = DockingUtilities.getSplitPane(dockable, JSplitPane.HORIZONTAL_SPLIT); if (split == null) return; if ( ( (Container) split.getLeftComponent()).isAncestorOf(dockable. getComponent())) { split.setDividerLocation(width); } else { split.setDividerLocation(1.0 - width); } } /** Changes the height of a dockable (the dockable must already be visible). * *

Note that this method works by modifying the divider location of the * nearest SplitContainer ancestor of the dockable (the first splitted vertically). * *

As this method must be called when the desktop is visible, a simple way to * do this is to add a window listener to the parent frame of the desktop, and call this * method from the windowOpened(WindowEvent) notification. * * @param height new height (if between 0 and 1, height is taken as a proportional height, * otherwise it is a pixel height. * * */ public void setDockableHeight(Dockable dockable, double height){ SplitContainer split = DockingUtilities.getSplitPane(dockable, JSplitPane.VERTICAL_SPLIT); if (split == null) return; if ( ( (Container) split.getTopComponent()).isAncestorOf(dockable. getComponent())) { split.setDividerLocation(height); } else { split.setDividerLocation(1 - height); } } /** Updates the resizing behaviour of the desktop in order to resize * this dockable (and keep others at fixed size). *

This method should be called at least once (prior to showing the desktop) with an * already docked dockable. *

If the dockable doesn't belong to the desktop containment hierarchy, * this method will do nothing. * @deprecated use setResizeWeight() in every dockKey for a better resizing behaviour * */ public void setAutoResizableDockable(Dockable dockable){ /*this.autoResizeableDockable = dockable; */ DockingUtilities.updateResizeWeights(dockingPanel); } /** Registers a dockable as belonging to a tab group. *

It is used to have a memory of grouped (tabbed) dockables in order to keep the * group together when dockable are restored from auto-hide mode. *

This method is generally called by the tabbed container management, and not directly * by the developper. * *

However, there is a case where calling this method can be usefull : * when, at startup, a desktop is built with multiple hidden dockables, and the developper wants * them to be grouped in a tab container when they are restored to the desktop. * *

note that the method is symetric when a group is empty : it such a case base and newTab * args can be swapped. * * @param base an already tabbed dockable * @param newTab a dockable to add to the tab group * *@since 1.1.2 */ public void addToTabbedGroup(Dockable base, Dockable newTab){//2005/07/13 /* this method is called when a dockable is added to a dockableTabbedContainer */ LinkedList group = (LinkedList) tabbedGroups.get(base); if (group == null){ group = new LinkedList(); group.add(base); tabbedGroups.put(base, group); } if (!group.contains(newTab)){ group.add(newTab); tabbedGroups.put(newTab, group); } } /** Unregisters a dockable from its current tab group (when it's removed from it). *

For an application developper, there should be no need to call this method as it is managed * internally by the framework, unless the developper wants to explicitely remove a component from * a tab group when this component is in the auto-hide state. *@since 1.1.2 */ public void removeFromTabbedGroup(Dockable dockable){ // 2005/07/13 /* package protected */ /* This method is invoked when a component is dragged outside of a tab group : meaning * the user doesn't want anymore this dockable to be grouped in that tab. * */ LinkedList group = (LinkedList) tabbedGroups.get(dockable); if (group != null){ tabbedGroups.remove(dockable); group.remove(dockable); if (group.size() == 1){ // end of grouping as there are no more dockables linked. Dockable d = (Dockable)group.removeFirst(); tabbedGroups.remove(d); } } } /** Creates the autohide expand panel to be used in this desktop. *

* This method gives a chance to the developer to override expand panel creation * and provide a custom subclass. */ protected AutoHideExpandPanel createAutoHideExpandPanel(){ return new AutoHideExpandPanel(); } /** used to track focus changes for DockableSelection events */ private class FocusHandler implements PropertyChangeListener, ChangeListener { /** this one is never null (except at first time) */ Dockable lastFocusedDockable; /** this one can be null between focusLost() and focusGained() */ Dockable currentDockable; // focusOwner public void propertyChange(PropertyChangeEvent e) { Component c = (Component) e.getNewValue(); while (c != null && ! (c instanceof SingleDockableContainer)){ c = c.getParent(); } if (c instanceof SingleDockableContainer){ SingleDockableContainer sdc = (SingleDockableContainer) c; currentDockable = sdc.getDockable(); if (sdc.getDockable() != lastFocusedDockable){ context.fireDockableSelectionChange(new DockableSelectionEvent(sdc.getDockable())); } lastFocusedDockable = sdc.getDockable(); } else { // c == null currentDockable = null; } } // This method is called whenever the selected tab of all TabbedDockableContainers changes public void stateChanged(ChangeEvent evt) { // our only problem is at startup : the focus may be out of the tabbed pane // and we are firing a false selection event. // @todo correct this behaviour by checking if the focus is not already // outside this component JTabbedPane pane = (JTabbedPane)evt.getSource(); TabbedDockableContainer tdc = ((TabbedDockableContainer)pane); Dockable selDockable = tdc.getSelectedDockable(); if (selDockable == null){ // this may happen when maximization occurs // ignore } else { currentDockable = selDockable; if (selDockable != lastFocusedDockable){ lastFocusedDockable = selDockable; context.fireDockableSelectionChange(new DockableSelectionEvent(selDockable)); } } } Dockable getCurrentDockable(){ return currentDockable; } } /** Returns the name of this desktop (used by workspace management) */ public String getDesktopName() { return desktopName; } /** Updates the name of this desktop (used by workspace management) */ public void setDesktopName(String desktopName) { this.desktopName = desktopName; } /** Returns the docking context used by this desktop (might be shared with other desktop). * * @since 2.1 */ public DockingContext getContext() { return context; } /** Updates the docking context used by this desktop. *

* Warning : this method should only be used by the framework itself : changing * a context "live" can have unpredicted and undesired side effect. * @since 2.1 */ public void setContext(DockingContext context) { this.context = context; } /** returns the currently maximized dockable * (or null if no dockable is in that state) */ public Dockable getMaximizedDockable() { if (maximizedComponent == null){ return null; } else { SingleDockableContainer maxContainer = (SingleDockableContainer)maximizedComponent; return maxContainer.getDockable(); } } /** combines a docking action event and vetoable state change event to accept or reject * a docking action. */ private boolean isDockingActionAccepted(DockingActionEvent dae, DockableStateWillChangeEvent dse){ boolean accepted = context.fireAcceptDockingAction(dae); if (accepted){ if (dse != null && dae.getInitialDockableState() != dae.getNextDockableState()){ return context.fireDockableStateWillChange(dse); } else { return true; } } else { return false; } } private void fireDockingAction(DockingActionEvent dae, DockableStateChangeEvent dse){ context.fireDockingActionPerformed(dae); if (dse != null && dae.getInitialDockableState() != dae.getNextDockableState()){ context.fireDockableStateChange(dse); } } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/DockingPanel.java0000644000175000017500000002313410573516350025442 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking; import com.vlsolutions.swing.docking.event.DockingActionSplitComponentEvent; import com.vlsolutions.swing.docking.event.DockingActionSplitDockableContainerEvent; import java.awt.Shape; import javax.swing.*; import com.vlsolutions.swing.docking.event.DockDragEvent; import com.vlsolutions.swing.docking.event.DockEvent; import java.awt.Rectangle; import java.awt.BorderLayout; import java.awt.geom.Rectangle2D; import com.vlsolutions.swing.docking.event.DockDropEvent; import java.awt.Point; import java.awt.Component; import java.awt.Container; import java.awt.Dimension; /** This class is responsible for the containment of a Dockable component. *

* Users of the VLDocking Framework should not call this class which is * a utility component of DockingDesktop. * *

* Please rely on DockingDesktop capabilities. * * @author Lilian Chamontin, vlsolutions. * @version 1.0 * @update 2005/11/08 Lilian Chamontin : added support for global width/height drop */ public class DockingPanel extends JPanel implements DockDropReceiver{ /** @todo see if we still need the DockDropReceiver */ /** Javabeans constructor */ public DockingPanel(){ super(new BorderLayout()); } /** act the same as a splitContainer : allow drop on the borders*/ public void processDockableDrag(DockDragEvent event) { scanContainer(event, false); } public void processDockableDrop(DockDropEvent event) { scanContainer(event, true); } private void acceptDrop(DockEvent event, DockingConstants.Split position){ Container dragContainer = event.getDragSource().getDockableContainer(); ( (DockDropEvent) event).acceptDrop(); if (dragContainer instanceof TabbedDockableContainer){ event.getDesktop().splitComponent(this, dragContainer, position); } else { event.getDesktop().splitComponent(this, event.getDragSource().getDockable(), position); } } private void acceptDrag(DockEvent event, DockingConstants.Split position, Shape shape){ Container dragContainer = event.getDragSource().getDockableContainer(); Dockable dockable = event.getDragSource().getDockable(); int initialState = dockable.getDockKey().getDockableState(); int nextState = DockableState.STATE_DOCKED; if (dragContainer instanceof TabbedDockableContainer){ event.setDockingAction(new DockingActionSplitDockableContainerEvent( event.getDesktop(), initialState, nextState, this, dragContainer, position, 0.5f)); } else { event.setDockingAction(new DockingActionSplitComponentEvent( event.getDesktop(), dockable, initialState, nextState, this, position, 0.5f)); } ( (DockDragEvent) event).acceptDrag(shape); } private void scanContainer(DockEvent event, boolean drop) { Point p = event.getMouseEvent().getPoint(); Rectangle compBounds = getBounds(); int distTop = p.y; int distLeft = p.x; int min = Math.min(distTop, distLeft); int distRight = compBounds.width - p.x; int distBottom = compBounds.height - p.y; int min2 = Math.min(distBottom, distRight); min = Math.min(min, min2); Dimension size = getSize(); Dockable dragged = event.getDragSource().getDockable(); // the drag size is the one of the parent dockable container Dimension draggedSize = dragged.getComponent().getParent().getSize(); int bestHeight = (int)Math.min(draggedSize.height , size.height * 0.5); int bestWidth = (int)Math.min(draggedSize.width , size.width * 0.5); if (min == distTop) { // dock on top if (drop) { acceptDrop(event, DockingConstants.SPLIT_TOP); } else { Rectangle2D r2d = new Rectangle2D.Float(0, 0, compBounds.width, bestHeight); acceptDrag(event, DockingConstants.SPLIT_TOP, r2d); } } else if (min == distLeft) { if (drop) { acceptDrop(event, DockingConstants.SPLIT_LEFT); } else { Rectangle2D r2d = new Rectangle2D.Float(0, 0, bestWidth, compBounds.height); acceptDrag(event, DockingConstants.SPLIT_LEFT, r2d); } } else if (min == distBottom) { if (drop) { acceptDrop(event, DockingConstants.SPLIT_BOTTOM); } else { Rectangle2D r2d = new Rectangle2D.Float(0, compBounds.height - bestHeight, compBounds.width, bestHeight); acceptDrag(event, DockingConstants.SPLIT_BOTTOM, r2d); } } else { // right if (drop) { acceptDrop(event, DockingConstants.SPLIT_RIGHT); } else { Rectangle2D r2d = new Rectangle2D.Float( compBounds.width - bestWidth, 0, bestWidth, compBounds.height); acceptDrag(event, DockingConstants.SPLIT_RIGHT, r2d); } } } public void resetToPreferredSize() { Component mainComp = getComponent(0); if (mainComp instanceof SplitContainer){ ((SplitContainer)mainComp).resetToPreferredSizes(); } } public String toString(){ return "DockingPanel["+hashCode()+"]"; // 2007/01/24 } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/DockingPreferences.java0000644000175000017500000002603310573516350026645 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking; import com.vlsolutions.swing.docking.ui.DockingUISettings; import java.awt.Color; import java.awt.image.BufferedImage; import javax.swing.BorderFactory; import javax.swing.JPopupMenu; import javax.swing.SwingConstants; import javax.swing.ToolTipManager; import javax.swing.UIManager; import javax.swing.border.Border; /** This is the centralized settings repository for managing docking look and feel. *

* It acts as a facade for installing common settings. *

* This class contains only high-level settings, like the heavyweight components support * or the global desktop style (shadowed or flat). To access low-level properties, use * the DockingUISettings class instead. * * @author Lilian Chamontin, VLSolutions * @since 1.1 * @see com.vlsolutions.swing.docking.ui.DockingUISettings */ public class DockingPreferences { private static boolean isLightWeightUsageEnabled = true; private static boolean isSingleHeavyWeightComponent = false; /** private stuff : use static methods only */ private DockingPreferences() { } public static final AutoHidePolicy getAutoHidePolicy(){ return AutoHidePolicy.getPolicy(); } /** A simple utility method to configure the docking framework to work properly with * heavyweight component. *

* Don't forget to invoke also the following general swing methods : *

     *      ToolTipManager.sharedInstance().setLightWeightPopupEnabled(false);
     *      JPopupMenu.setDefaultLightWeightPopupEnabled(false);        
     *
*

* If you are sure you will always use heavyweight component, you can replace this * method invocation by initHeavyWeightUsage(), which will do all the work for you * (even the general swing methods invocation). * */ public static void setLightweigthComponentEnabled(boolean lightweight){ isLightWeightUsageEnabled = lightweight; } public static boolean isLightWeightUsageEnabled(){ return isLightWeightUsageEnabled; } /** Notifies the framework that there is only one dockable that is heavyweight. *

This allows optimizations and workarounds (for properly using the JDIC WebBrowser * for example). */ public static void setSingleHeavyWeightComponent(boolean single){ isSingleHeavyWeightComponent = single; } public static boolean isSingleHeavyWeightComponent(){ return isSingleHeavyWeightComponent; } /** Facade method used to allow mixing of lightweight and heavyweight components in the * desktop. *

* This method is a shortcut for : *

     *        ToolTipManager.sharedInstance().setLightWeightPopupEnabled(false);
     *        JPopupMenu.setDefaultLightWeightPopupEnabled(false);        
     *        setLightweigthComponentEnabled(false);
     *        getAutoHidePolicy().setExpansionDuration(0);
     * 
*/ public static void initHeavyWeightUsage(){ // for now, there are only two methods used. ToolTipManager.sharedInstance().setLightWeightPopupEnabled(false); JPopupMenu.setDefaultLightWeightPopupEnabled(false); setLightweigthComponentEnabled(false); getAutoHidePolicy().setExpansionDuration(0); } /** Facade method used to allow mixing of lightweight and heavyweight components in the * desktop. */ public static void initHeavyWeightUsage(boolean isSingleHeavyWeightComponent){ initHeavyWeightUsage(); setSingleHeavyWeightComponent(isSingleHeavyWeightComponent); } /** Convenience method to use the VLDocking 1.0 layout and border style (with shadows around dockables) */ public static void setShadowDesktopStyle(){ DockingUISettings.getInstance().installUI(); UIManager.put("DockView.singleDockableBorder", new ShadowBorder()); UIManager.put("DockView.tabbedDockableBorder", new ShadowBorder(false)); UIManager.put("TabbedDockableContainer.tabPlacement", new Integer(SwingConstants.BOTTOM)); } /** Convenience method to use the VLDocking 2.0 layout and border style. *

* The new "flat style" uses light borders around dockables and top tab placements. *

* This style is the new default one, so there is no need to call this method unless you want * to swap dynamically between desktop styles. */ public static void setFlatDesktopStyle(){ DockingUISettings.getInstance().installUI(); // flat style is the default (outside : empty 1 pix / inside : hightlight-top-left + shadow-bottom-right Color shadow = UIManager.getColor("controlShadow"); Color highlight = UIManager.getColor("controlLtHighlight"); Border innerFlatSingleBorder = BorderFactory.createCompoundBorder( BorderFactory.createMatteBorder(1,1,0,0, highlight), BorderFactory.createMatteBorder(0,0,1,1, shadow)); Border flatSingleBorder = BorderFactory.createCompoundBorder( BorderFactory.createEmptyBorder(1,1,1,1), innerFlatSingleBorder); UIManager.put("DockView.singleDockableBorder", flatSingleBorder); UIManager.put("DockView.tabbedDockableBorder", null); UIManager.put("TabbedDockableContainer.tabPlacement", new Integer(SwingConstants.TOP)); } /** Another docking style with ligh dots between dockables. */ public static void setDottedDesktopStyle(){ DockingUISettings.getInstance().installUI(); Color shadow = UIManager.getColor("controlShadow"); Color highlight = UIManager.getColor("controlLtHighlight"); Border innerFlatSingleBorder = BorderFactory.createCompoundBorder( BorderFactory.createMatteBorder(1,1,0,0, highlight), BorderFactory.createMatteBorder(0,0,1,1, shadow)); UIManager.put("DockView.singleDockableBorder", innerFlatSingleBorder); //BorderFactory.createLineBorder(shadow)); UIManager.put("DockView.tabbedDockableBorder", null); UIManager.put("TabbedDockableContainer.tabPlacement", new Integer(SwingConstants.TOP)); UIManager.put("SplitContainer.drawDotsDelimitors", Boolean.TRUE); } /** Another docking style with custom tiles between dockables. */ public static void setCustomSplitDesktopStyle(BufferedImage horizontalTile, BufferedImage verticalTile){ DockingUISettings.getInstance().installUI(); //UIManager.put("DockView.singleDockableBorder", null); UIManager.put("DockView.tabbedDockableBorder", null); UIManager.put("TabbedDockableContainer.tabPlacement", new Integer(SwingConstants.TOP)); UIManager.put("SplitContainer.drawDotsDelimitors", Boolean.FALSE); UIManager.put("SplitContainer.hImage", horizontalTile); UIManager.put("SplitContainer.vImage", verticalTile); UIManager.put("SplitContainer.useCustomImages", Boolean.TRUE); } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/DockingSelectorDialog.java0000644000175000017500000003526710573516350027315 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking; import javax.swing.*; import java.awt.*; import java.util.*; import java.awt.event.*; import java.awt.event.ActionEvent; import javax.swing.table.*; import java.util.ArrayList; /** A Helper class providing information about the visibility of user components. *

* This dialog shows which user components are docked, auto-hidden, * not visible, and is capable of dynamicaly altering the dockingpanel layout * on user selection (for example, to show an unvisible component). * *

* User components shown are those which are already docked and those * which have been registered with the registerDockableComponent() method of DockingPanel. * *

* Example of usage : *

 * Frame f = ...  // frame containing the docking panel
 * DockingPanel dockingPanel = ...
 * DockingSelectorDialog dlg = new DockingSelectorDialog(f);
 * dlg.setDockingPanel(dockingPanel);
 * dlg.pack();
 * dlg.setLocationRelativeTo(f);
 * dlg.setVisible(true); // modal
 *
 * // optional
 * if (dlg.getClosingState() == DockingSelectorDialog.CONFIRM){
 *    // do something more
 * }
 * 
* * @see DockingPanel * * @author Lilian Chamontin, vlsolutions. * @version 1.0 */ public class DockingSelectorDialog extends JDialog { /** Closing state of the dialog when the user has selected the confirm option * @see #getClosingState() */ public static final int CONFIRM = 0; /** Closing state of the dialog when the user has selected the cancel option * @see #getClosingState() */ public static final int CANCEL = 1; private DockablesTableModel model; private DockingDesktop desktop; private static final String TITLE = "Docking Configuration"; private JButton confirmButton = new JButton("Ok"); private JButton cancelButton = new JButton("Cancel"); private JTable table = new JTable(); JLabel wizardLabel = new JLabel() { public void paintComponent(Graphics g) { Graphics2D g2 = (Graphics2D) g; Paint p = g2.getPaint(); g2.setPaint(new GradientPaint(0, 0, Color.WHITE, getWidth(), 0, getBackground())); g2.fillRect(0, 0, getWidth(), getHeight()); g2.setPaint(p); super.paintComponent(g); } }; private String wizardLabelText = "

This window helps you to manage the " + " views composing your application workspace.

" + "

By clicking on the table checkboxes below, you can select if " + "a view will be diplayed or not

" + "

Click on the Ok button to apply your changes or on " + "the Cancel button if you do not want to save your changes." + " "; private int closingState = CANCEL; private HashMap visibleViews = new HashMap(); // DockableState / Boolean (visible?) /** Default constructor. *

modal dialog with DISPOSE_ON_CLOSE option, * needs a pack() and setVisible(true) after creation * */ public DockingSelectorDialog() { setModal(true); setDefaultCloseOperation(DISPOSE_ON_CLOSE); setTitle(TITLE); init(); } /** Constructor for Dialog parent window. *

modal dialog with DISPOSE_ON_CLOSE option, * needs a pack() and setVisible(true) after creation. */ public DockingSelectorDialog(Dialog owner) { super(owner, true); setDefaultCloseOperation(DISPOSE_ON_CLOSE); setTitle(TITLE); init(); } /** Constructor for Frame parent window. *

modal dialog with DISPOSE_ON_CLOSE option, * needs a pack() and setVisible(true) after creation. * */ public DockingSelectorDialog(Frame owner) { super(owner, true); setDefaultCloseOperation(DISPOSE_ON_CLOSE); setTitle(TITLE); init(); } private void init(){ getContentPane().setLayout(new BorderLayout(5,5)); JScrollPane jsp = new JScrollPane(table); jsp.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(0,5,0,5), jsp.getBorder())); getContentPane().add(jsp, BorderLayout.CENTER); confirmButton.setToolTipText("Close this window and update the views"); cancelButton.setToolTipText("Close this window without updating the views"); confirmButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent actionEvent) { closingState = CONFIRM; for (int i = 0; i < model.states.length; i++) { DockableState state = model.states[i]; boolean newVisible = ((Boolean)visibleViews.get(state)).booleanValue(); boolean oldVisible = state.getState() != DockableState.STATE_CLOSED; if ( oldVisible != newVisible){ if (newVisible){ desktop.addDockable(state.getDockable(), state.getPosition()); } else { desktop.close(state.getDockable()); } } } DockingSelectorDialog.this.dispose(); } }); Action closeAction = new AbstractAction("Cancel"){ public void actionPerformed(ActionEvent actionEvent) { closingState = CANCEL; DockingSelectorDialog.this.dispose(); } }; cancelButton.setAction(closeAction); JPanel buttons = new JPanel(new FlowLayout(FlowLayout.TRAILING)); JPanel grid = new JPanel(new GridLayout(1,0, 5, 0)); // buttons of same size grid.add(confirmButton); grid.add(cancelButton); buttons.add(grid); getContentPane().add(buttons, BorderLayout.SOUTH); wizardLabel.setText(wizardLabelText); wizardLabel.setBorder( BorderFactory.createCompoundBorder( BorderFactory.createMatteBorder(0,0,1,0, Color.DARK_GRAY), BorderFactory.createEmptyBorder(5,5,5,5))); getContentPane().add(wizardLabel, BorderLayout.NORTH); // ESCAPE == CLOSE KeyStroke ESC = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0); getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put( ESC, "CLOSE"); getRootPane().getActionMap().put("CLOSE", closeAction); table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put( ESC, "CLOSE" ); table.getActionMap().put("CLOSE", closeAction ); addWindowListener(new WindowAdapter(){ public void windowOpened(WindowEvent e){ getRootPane().setDefaultButton(confirmButton); } }); } /** Change the confirm button text (hook for i18n)*/ public void setConfirmButtonText(String text){ confirmButton.setText(text); } /** Change the cancel button text (hook for i18n)*/ public void setCancelButtonText(String text){ cancelButton.setText(text); } /** Change the confirm button tooltip text (hook for i18n)*/ public void setConfirmButtonTooltipText(String text){ confirmButton.setToolTipText(text); } /** Change the cancel button tootip text (hook for i18n)*/ public void setCancelButtonTooltipText(String text){ cancelButton.setToolTipText(text); } /** Change the wizard label text (an explanation of the behaviour of this dialog). *

HTML format is supported like in any JLabel. * */ public void setWizardLabelText(String wizardLabelText) { this.wizardLabel.setText(wizardLabelText); } /** Requiered to initialize this dialog. *

Invoke this method before packing the dialog. * * */ public void setDockingDesktop(DockingDesktop desktop){ this.desktop = desktop; DockableState [] states = desktop.getDockables(); Arrays.sort(states); this.model = new DockablesTableModel(states); table.setModel(model); table.getColumnModel().getColumn(0).setPreferredWidth(25); table.getColumnModel().getColumn(1).setPreferredWidth(200); table.getColumnModel().getColumn(2).setPreferredWidth(70); table.setPreferredScrollableViewportSize(new Dimension(300,300)); table.setCellSelectionEnabled(true); table.setShowVerticalLines(false); table.setRowHeight(20); } /** Returns the users close choice as CONFIRM or CANCEL (remember this dialog is modal). *

Use this method if you need to know how is was closed. * If the used has confirmed, the docking panel is automaticaly updated * by the confirm button action. */ public int getClosingState(){ return closingState; } class DockablesTableModel extends AbstractTableModel{ String[] colNames = {" ", "Name", "Visible"}; private DockableState [] states; DockablesTableModel(DockableState [] states) { this.states = states; for (int i = 0; i < states.length; i++) { visibleViews.put(states[i], states[i].getState() == DockableState.STATE_CLOSED ? Boolean.FALSE : Boolean.TRUE); } } public int getColumnCount() { return colNames.length; } public int getRowCount() { return states.length; } public String getColumnName(int col){ return colNames[col]; } public boolean isCellEditable(int row, int col){ if (col != 2) return false; Dockable dockable = states[row].getDockable(); if (dockable.getDockKey().isCloseEnabled()) { return true; } else { return false; } } public Class getColumnClass(int col) { switch (col) { case 0: return Icon.class; case 1: return String.class; case 2: return Boolean.class; } return null; } public Object getValueAt(int row, int col) { DockableState state = states[row]; switch (col) { case 0: return state.getDockable().getDockKey().getIcon(); case 1: return state.getDockable().getDockKey().getName(); case 2: return (Boolean) visibleViews.get(state); } return null; } public void setValueAt(Object v, int row, int col){ DockableState state = states[row]; visibleViews.put(state, v); } } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/DockingUtilities.java0000644000175000017500000005474710573516350026374 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking; import java.awt.*; import java.awt.peer.LightweightPeer; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import javax.swing.*; /** Utility class implementing search/replace algorithms used by the framework. *

* This class is not inteded for API users, it should be let to framework developpers. * * @author Lilian Chamontin, vlsolutions. * @version 1.0 * */ public class DockingUtilities { private DockingUtilities(){ // singleton } /** returns the first DockableContainer which is parent of this dockable component */ public static DockableContainer findDockableContainer(Dockable dockable){ if (dockable == null) return null; Component comp = dockable.getComponent(); if (comp == null) return null; while (comp != null){ if (comp instanceof DockableContainer){ return (DockableContainer) comp; } comp = comp.getParent(); } return null; } /** returns the first DockableContainer which is parent of this dockable component */ public static SingleDockableContainer findSingleDockableContainer(Dockable dockable){ if (dockable == null) return null; Component comp = dockable.getComponent(); if (comp == null) return null; while (comp != null){ if (comp instanceof SingleDockableContainer){ return (SingleDockableContainer) comp; } comp = comp.getParent(); } return null; } /** Returns the first TabbedDockableContainer which is parent of this dockable component, or * null is there isn't any. * */ public static TabbedDockableContainer findTabbedDockableContainer(Dockable dockable){ if (dockable == null) return null; Component comp = dockable.getComponent(); if (comp == null) return null; /* while (comp != null){ //2005/10/10 if (comp instanceof TabbedDockableContainer){ return (TabbedDockableContainer) comp; } comp = comp.getParent(); } */ while (comp != null){ // new version to support compoundDockable : stop after the first parent of // the first SingleDockableContainer found if (comp instanceof SingleDockableContainer){ comp = comp.getParent(); if (comp instanceof TabbedDockableContainer){ return (TabbedDockableContainer)comp; } else { return null; } } comp = comp.getParent(); } return null; } private static void swapComponents(SplitContainer split1, SplitContainer split2, Component comp1, Component comp2){ boolean isLeft1 = split1.getLeftComponent()== comp1; int divider1 = split1.getDividerLocation(); if (split1 == split2){ split1.remove(comp1); split1.remove(comp2); if (isLeft1){ split1.setLeftComponent(comp2); split1.setRightComponent(comp1); } else { split1.setLeftComponent(comp1); split1.setRightComponent(comp2); } split1.setDividerLocation(divider1); split1.revalidate(); } else { boolean isLeft2 = split2.getLeftComponent()== comp2; int divider2 = split2.getDividerLocation(); split1.remove(comp1); split2.remove(comp2); if (isLeft1){ split1.setLeftComponent(comp2); } else { split1.setRightComponent(comp2); } split1.setDividerLocation(divider1); if (isLeft2){ split2.setLeftComponent(comp1); } else { split2.setRightComponent(comp1); } split2.setDividerLocation(divider2); } } /** Swaps two toplevel DockableContainers (their parent must be a SplitContainer) */ public static void swapComponents(Component comp1, Component comp2){ Container parent1 = comp1.getParent(); Container parent2 = comp2.getParent(); if (parent1 instanceof SplitContainer){ if (parent2 instanceof SplitContainer){ swapComponents((SplitContainer) parent1, (SplitContainer) parent2, comp1, comp2); } else { // nothing } } } /** Invoked every time the layout is changed, to rebuild the weighting of split containers */ public static void updateResizeWeights(DockingPanel dockingPanel){ if (dockingPanel.getComponentCount() > 0){ resetSplitWeight(dockingPanel.getComponent(0)); } } private static float resetSplitWeight(Component comp){ if (comp instanceof SplitContainer){ SplitContainer split = (SplitContainer) comp; float leftWeight = resetSplitWeight(split.getLeftComponent()); float rightWeight = resetSplitWeight(split.getRightComponent()); float sum = leftWeight + rightWeight; if (sum == 0){ split.setResizeWeight(0.5); // half weight for each side return 0; } else if (leftWeight == 0){ // and rightWeight != 0 split.setResizeWeight(0); // every resize goes to the right return rightWeight; } else if (rightWeight == 0){ // and leftWeight != 0 split.setResizeWeight(1); // every resize goes to the left return leftWeight; } else { float proportion = leftWeight / sum; // when near 0 => right, when near 1 => left split.setResizeWeight(proportion); return Math.max(leftWeight, rightWeight); } } else if (comp instanceof SingleDockableContainer){ return ((SingleDockableContainer)comp).getDockable().getDockKey().getResizeWeight(); } else if (comp instanceof TabbedDockableContainer){ TabbedDockableContainer tab = (TabbedDockableContainer) comp; float max = 0; for (int i=0; i < tab.getTabCount(); i++){ Dockable d = tab.getDockableAt(i); if (d != null){ float v = d.getDockKey().getResizeWeight(); if (v > max) { max = v; } } } return max; } else if (comp instanceof MaximizedComponentReplacer){ //2007/01/18 // ignore as this component replaces the maximized dockable in the // docking container hierarchy } else { System.err.println("Wrong hierarchy in docking panel (resetSplitWeight error) " + comp); } return 0; } /** Child replacement */ public static void replaceChild(Container parent, Component child, Component newChild){ //System.out.println("replace child : PARENT=" + parent + ", CHILD=" + child + ", NEW=" + newChild); if (parent instanceof SplitContainer) { final SplitContainer split = (SplitContainer) parent; final int location = split.getDividerLocation(); if (split.getLeftComponent() == child) { split.remove(child); split.setLeftComponent(newChild); } else if (split.getRightComponent() == child) { split.remove(child); split.setRightComponent(newChild); } else { throw new IllegalArgumentException("wrong hierarchy"); } // SwingUtilities.invokeLater(new Runnable() { // public void run() { split.setDividerLocation(location); split.revalidate(); split.doLayout(); // } // }); } else if (parent instanceof TabbedDockableContainer){ // 2005/07/12... // interface trick : we need to access the JTabbedPane internals // the newChild can be a dummy JComponent (when used in maximize/restore) // or a fully featured dockable (other usages) // this is not really clean : it's the problem when using interfaces over subclasses... if (parent instanceof JTabbedPane){ TabbedDockableContainer tparent = (TabbedDockableContainer) parent; JTabbedPane jtp = (JTabbedPane) tparent; int index = jtp.indexOfComponent(child); jtp.remove(index); if (newChild instanceof SingleDockableContainer){ tparent.addDockable(((SingleDockableContainer) newChild).getDockable(), index); jtp.setSelectedIndex(index); } else { // dummy component jtp.add(newChild, index); jtp.setSelectedIndex(index); } } else { throw new RuntimeException("Unknown TabbedDockableContainer"); } // ...2005/07/12 } else { // we're on top level (panel with borderlayout) parent.remove(child); parent.add(newChild, BorderLayout.CENTER); parent.invalidate(); parent.validate(); } } /** Returns the split pane containing this dockable (if any), or null if this dockable * isn't contained in a splitpane. *

* If the dockable is nested in a TabbedDockableContainer, the split pane returned will * be the one containing the tabbed container (if any). * * */ public static SplitContainer getSplitPane(Dockable dockable, int orientation ){ Component comp = dockable.getComponent(); boolean found = false; while (comp != null && !found){ if (comp instanceof SplitContainer && ((SplitContainer)comp).getOrientation() == orientation){ found = true; } else { comp = comp.getParent(); } } return (SplitContainer)comp; } /** A utility method to find the first single dockable container ancestor of the given component. *

* This method may return null if no SingleDockableContainer ancestor is found. */ public static SingleDockableContainer findSingleDockableContainerAncestor(Component component){ Component parent = component.getParent(); while (parent != null && ! (parent instanceof SingleDockableContainer)){ parent = parent.getParent(); } return (SingleDockableContainer)parent; } /** Utility method to find out if a component is heavyweight (of if it contains a heavyweight comp)*/ public static boolean isHeavyWeightComponent(Component comp){ if (comp instanceof Container){ // short cut Object peer = comp.getPeer(); if (!(peer == null || peer instanceof LightweightPeer)){ // it's not a lightweight return true; } else { // long way Container c = (Container) comp; for (int i=0; i < c.getComponentCount(); i++){ Component child = c.getComponent(i); if (isHeavyWeightComponent(child)){ return true; } } return false; } } else { Object peer = comp.getPeer(); return !(peer == null || peer instanceof LightweightPeer); } } /** Returns whether we can use the secured and 1.5 MouseInfo class */ public static boolean canUseMouseInfo(){ if (System.getProperty("java.version").compareTo("1.5")>=0){ return getMouseLocation() != null; } else { return false; // not present in pre 1.5 versions } } /** Returns the mouse location on screen or null if ran in an untrusted environement/ java 1.4 */ public static Point getMouseLocation(){ try { //Point mouseLocation = MouseInfo.getPointerInfo().getLocation(); // this class in not compatible with 1.4 // so instead we use reflection for allowing 1.4 compilation Class mouseInfoClass = Class.forName("java.awt.MouseInfo"); final Class [] noArgs = new Class[0]; Method m = mouseInfoClass.getMethod("getPointerInfo", noArgs); Object pointerInfo = m.invoke(null, null); Class pointerInfoClass = Class.forName("java.awt.PointerInfo"); Method getLocationMethod = pointerInfoClass.getMethod("getLocation", noArgs); Point mouseLocation = (Point)getLocationMethod.invoke(pointerInfo, null); return mouseLocation; } catch (ClassNotFoundException ignore){ } catch (NoSuchMethodException ignore){ } catch (IllegalAccessException e){ } catch (InvocationTargetException ignore){ } return null; } /** packs a detached dockable, regardless of its type (frame or dialog) */ public static void pack(FloatingDockableContainer fdc){ //2006/02/20 if (fdc instanceof JFrame){ ((JFrame) fdc).pack(); } else if (fdc instanceof JDialog){ ((JDialog) fdc).pack(); } } /** resizes a detached dockable, regardless of its type (frame or dialog) */ public static void setSize(FloatingDockableContainer fdc, Dimension size){ //2006/02/20 if (fdc instanceof JFrame){ ((JFrame) fdc).setSize(size); } else if (fdc instanceof JDialog){ ((JDialog) fdc).setSize(size); } } /** validates a detached dockable, regardless of its type (frame or dialog) */ public static void validate(FloatingDockableContainer fdc){ //2006/02/20 ((Window)fdc).validate(); } /** positions a detached dockable, regardless of its type (frame or dialog) */ public static void setLocation(FloatingDockableContainer fdc, Point location){ //2006/02/20 ((Window)fdc).setLocation(location); } /** positions a detached dockable, regardless of its type (frame or dialog) */ public static void setLocationRelativeTo(FloatingDockableContainer fdc, Component rel){ //2006/02/20 ((Window)fdc).setLocationRelativeTo(rel); } /** shows a detached dockable, regardless of its type (frame or dialog) */ public static void setVisible(FloatingDockableContainer fdc, boolean visible){ //2006/02/20 ((Window)fdc).setVisible(visible); } /** disposes a detached dockable, regardless of its type (frame or dialog) */ public static void dispose(FloatingDockableContainer fdc) { ((Window)fdc).dispose(); } /** returns the root pane used by this detached dockable container, regardless of its type (frame or dialog)*/ public static JRootPane getRootPane(FloatingDockableContainer fdc) { if (fdc instanceof JFrame){ return ((JFrame) fdc).getRootPane(); } else if (fdc instanceof JDialog){ return ((JDialog) fdc).getRootPane(); } else { return null; // not reachable } } static void setBounds(FloatingDockableContainer fdc, Rectangle bounds) { ((Window)fdc).setBounds(bounds); } /** Creates a list of all dockable children contained in the given compound dockable. *

If the compound dockable contains another compound dockable this one is also added, * along with its own children. * @return an ArrayList of Dockable */ public static ArrayList findCompoundDockableChildren(CompoundDockable compoundDockable) { ArrayList list = new ArrayList(); CompoundDockingPanel cdp = (CompoundDockingPanel) compoundDockable.getComponent(); fillCompoundChildren(cdp, list); return list; } private static void fillCompoundChildren(CompoundDockingPanel cdp, ArrayList list) { if (cdp.getComponentCount() > 0){ Component c = cdp.getComponent(0); fillCompoundChildren(c, list); } } private static void fillCompoundChildren(Component c, ArrayList list) { if (c instanceof CompoundDockingPanel){ fillCompoundChildren((CompoundDockingPanel)c, list); } else if (c instanceof SingleDockableContainer){ list.add(((SingleDockableContainer)c).getDockable()); } else if (c instanceof SplitContainer){ fillCompoundChildren(((SplitContainer)c).getLeftComponent(), list); fillCompoundChildren(((SplitContainer)c).getRightComponent(), list); } else if (c instanceof TabbedDockableContainer){ TabbedDockableContainer tdc = (TabbedDockableContainer)c; for (int i=0; i < tdc.getTabCount(); i++){ Dockable d = tdc.getDockableAt(i); if (d instanceof CompoundDockable){ list.add(d); CompoundDockingPanel cdp = (CompoundDockingPanel) d.getComponent(); fillCompoundChildren(cdp, list); } else { list.add(d); } } } } /** checks if this dockable is a child of a compound dockable */ public static boolean isChildOfCompoundDockable(Dockable dockable) { Container container = dockable.getComponent().getParent(); while (container != null){ if (container instanceof CompoundDockingPanel && ((CompoundDockingPanel)container).getDockable() != dockable){ // avoid returning true if the dockable if itself a compound return true; } container = container.getParent(); } return false; } /** searches up the dockable container hierarchy and returns the first ancestor * which is a CompoundDockable (or null if not found). */ public static Container findCompoundAncestorContainer(Dockable dockable) { Container container = dockable.getComponent().getParent(); while (container != null){ if (container instanceof CompoundDockingPanel && ((CompoundDockingPanel)container).getDockable() != dockable){ // avoid returning true if the dockable if itself a compound return container; } container = container.getParent(); } return null; } /** searches up the dockable container hierarchy and returns the dockable state of the * last (top most) ancestor which is a CompoundDockable (or -1 if not found). */ public static int getTopMostAncestorContainerState(Dockable dockable) { Container container = dockable.getComponent().getParent(); Container topMostContainer = null; while (container != null){ if (container instanceof CompoundDockingPanel && ((CompoundDockingPanel)container).getDockable() != dockable){ // avoid returning true if the dockable if itself a compound topMostContainer = container; } container = container.getParent(); } if (topMostContainer != null){ CompoundDockingPanel cdp = (CompoundDockingPanel) topMostContainer; return cdp.getDockable().getDockKey().getDockableState(); } return -1; } /** Returns a DockableState value corresponding to this component or -1 if not found. *

* Two states are currently managed : docked and floating (not hidden/maximized/closed). */ public static int getDockableStateFromHierarchy(Component comp) { if (comp == null){ return -1; } while (comp != null){ if (comp instanceof DockingPanel){ return DockableState.STATE_DOCKED; } else if (comp instanceof FloatingDockableContainer){ return DockableState.STATE_FLOATING; } comp = comp.getParent(); } return -1; } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/DragControler.java0000644000175000017500000017414010573516350025655 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking; import java.awt.event.*; import java.awt.*; import java.awt.image.BufferedImage; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import javax.swing.*; import java.awt.geom.*; import com.vlsolutions.swing.docking.event.*; import java.lang.reflect.Method; /** The component that manages mouse events related to docking. * * @author Lilian Chamontin, vlsolutions. * @version 1.0 * @update 2005/10/10 Lilian Chamontin : Updated to support multiple windows * (like the FloatingDockableContainers). * @update 2005/11/01 Lilian Chamontin : Improved shape and label painting * @update 2005/11/01 Lilian Chamontin : added support for customizable cursors * @update 2005/11/01 Lilian Chamontin : added a dead zone for floating (around start drag point) to avoid * unwanted detach and to allow cancelling a detach action * @update 2005/11/10 Lilian Chamontin : added support for hot swap, and MultipleDragSource * unwanted detach and to allow cancelling a detach action * @update 2006/03/16 Lilian Chamontin : patched a NPE occuring sometimes but not reproducible easily * @update 2007/01/06 Lilian Chamontin : fixed a DnD bug when droping on a tab bottom border, * the split was replaced by a createTab * */ class DragControler implements MouseListener, MouseMotionListener { /* package protected class !! * */ private static boolean isLightWeight = DockingPreferences.isLightWeightUsageEnabled(); /** This new object is responsible for painting shapes on lightweight components * or heavyweight components */ //private ShapePainterStrategy shapePainterStrategy = new ShapePainterStrategy(); private ShapePainterStrategy currentShapePainterStrategy; private boolean startDrag; private Shape dropShape; private boolean isFloatingShape = false; // true during floating Dnd private DockableDragSource dockableDragSource; private Point dragPoint; // !=null means that drag is occuring private Point startDragPoint; // for offset drawing private DockDropReceiver dropReceiver; // the component receiving the drop private DockingDesktop desktop; private boolean ignoreDrag; // flag to ignore a drag operation private boolean paintFloatingDragShape = UIManager.getBoolean("FloatingContainer.paintDragShape"); private DockingContext dockingContext; private boolean paintBackgroundUnderDragRect = UIManager.getBoolean("DragControler.paintBackgroundUnderDragRect"); /** instantiates a controler for a given docking panel*/ DragControler(DockingDesktop desktop) { this.desktop = desktop; this.dockingContext = desktop.getContext(); } /** process mouse clicks on DockableDragSource */ public void mouseClicked(MouseEvent e) { } /** process mouse entered on DockableDragSource (nothing yet) */ public void mouseEntered(MouseEvent e) { } /** process mouse exit on DockableDragSource (nothing yet) */ public void mouseExited(MouseEvent e) { } /** process mouse pressed on DockableDragSource : prepares a drag operation */ public void mousePressed(MouseEvent e) { if (SwingUtilities.isLeftMouseButton(e)){ startDrag = true; ignoreDrag = false; } else { if (dragPoint != null){ // we were dragging cancelDrag(); } /* if ((e.getModifiersEx() & MouseEvent.BUTTON1_DOWN_MASK)>0){ // in the middle of a drag gesture } else { ignoreDrag = true; }*/ } } /** process mouse released on DockableDragSource */ public void mouseReleased(MouseEvent e) { if (! SwingUtilities.isLeftMouseButton(e)){ // not the trigger button if (dragPoint != null){ // we were dragging notifyDragSourceDragComplete(false); cancelDrag(); } } else { // left button // are we above an insertion point ? if (ignoreDrag){ return; } try { boolean dropped = false; if (dragPoint != null && dockableDragSource != null){ dropped = processMouseReleased(e); } notifyDragSourceDragComplete(dropped); } finally { // clean up state variables notifyDragSourceDragComplete(false); cancelDrag(); } } } /** invoked only when a drag gesture has beed done * @return true if the dockable has been dropped. */ private boolean processMouseReleased(MouseEvent e){ // 2007/01/08 updated to return a boolean //Component underMouse = findComponentAt(desktop, dragPoint.x, dragPoint.y); DockableDragSource dragSource = ( (DockableDragSource) e.getSource()); this.dragPoint = SwingUtilities.convertPoint( (Component) e.getSource(), e.getPoint(), desktop); UnderMouseInfo umInfo = findComponentUnderMouse(e); Component underMouse = umInfo.underMouse; Component underMouseNullDesktop = null; DockingDesktop targetDesktop = umInfo.desktop; //findNearestNestedDesktop(underMouse);//umInfo.desktop if (targetDesktop == null){ underMouseNullDesktop = findDropReceiverOutsideDesktop(underMouseNullDesktop, e); } ShapePainterStrategy shapePainterStrategy = getShapePainter(underMouse, dragSource); int dx = dragPoint.x - startDragPoint.x; int dy = dragPoint.y - startDragPoint.y; if (Math.abs(dx) < 20 && Math.abs(dy) < 10){ // deny drag gesture when too near from start point 2005/11/15 return false; } if (targetDesktop == null){ // deny drag gesture when desktops aren't compatible if (underMouseNullDesktop != null){ // we've found a dock drop receiver // we send a really simple event DockDropEvent event = new DockDropEvent(desktop, dragSource, e); ((DockDropReceiver)underMouseNullDesktop).processDockableDrop(event); // this event will be ignored } return false; } else if (targetDesktop.getContext() != desktop.getContext()){ //2006/09/11 // contexts not compatible, stop here return false; } // 2005/11/08 support for full height/width docking DockingPanel dp = targetDesktop.getDockingPanel(); Insets i = targetDesktop.getDockingPanelInsets(); Rectangle deskBounds = new Rectangle(i.left, i.top, targetDesktop.getWidth() - i.left - i.right, targetDesktop.getHeight() - i.top - i.bottom); Rectangle innerBounds = new Rectangle(deskBounds); innerBounds.x += 5; innerBounds.y += 5; innerBounds.width -= 10; innerBounds.height -= 10; if (deskBounds.contains(dragPoint) && ! innerBounds.contains(dragPoint)){ // at less than 5 pixels from a order, promote DockingPanel as the receiver underMouse = dp; } // move up hierarchy till we find a drop receiver while (underMouse != null && underMouse != targetDesktop && ! (underMouse instanceof DockDropReceiver)) { underMouse = underMouse.getParent(); } umInfo.underMouse = underMouse; // resync if (underMouse == null){ // || isAncestorOf(dockableDragSource.getDockableContainer(), underMouse)){ 2007/01/08 moved to implementations // it's not possible to drop a parent on one of its children if (underMouse instanceof DockDropReceiver){ // but we still have to use the reference on drop receiver to disaplay a floating drag shape this.dropReceiver = (DockDropReceiver) underMouse; } DropProcess dropProcess = new DropProcess(e, dockableDragSource, umInfo); if (dropProcess.canDockableBeDetached() && dropProcess.checkDockableWillBeDetached()){ Point location = new Point(e.getPoint()); SwingUtilities.convertPointToScreen(location, e.getComponent()); dropProcess.setFloating(location); return true; } else { // refused (vetoed) return false; } } else if (underMouse instanceof DockDropReceiver && e.isControlDown()) { //2005/11/08 HOT SWAP FUNCTION processHotSwap(underMouse, e.getComponent(), null, true); return true; } else if (underMouse instanceof DockDropReceiver) { // MouseEvent convertMouse; DropProcess process = new DropProcess(e, dockableDragSource, umInfo); DockDragEvent event = process.findAcceptableEvent(e); if (event.isDragAccepted() && process.isDockingActionAccepted()) {// triggers vetoable listeners return process.dropIfPossible(); } else if (process.canDockableBeDetached() // Not accepted on the desktop //2005/10/07 && process.checkDockableWillBeDetached()){ Point location = new Point(e.getPoint()); SwingUtilities.convertPointToScreen(location, e.getComponent()); process.setFloating(location); return true; } else { // vetoed, nothing can be be done return false; } } else { /*if (underMouse == null){ */ // not under a droppable zone DropProcess process = new DropProcess(e, dockableDragSource, umInfo); if (process.canDockableBeDetached() && process.checkDockableWillBeDetached()){ Point location = new Point(e.getPoint()); SwingUtilities.convertPointToScreen(location, e.getComponent()); process.setFloating(location); return true; } else { return false; } } } /** This method cancels the current drag gesture. *

* It can be used for example by a key listener reacting to the escape key * *@since 2.0.1 */ public void cancelDrag(){ this.ignoreDrag = true; this.dropShape = null; this.dockableDragSource = null; this.startDrag = true; this.dragPoint = null; if (currentShapePainterStrategy != null){ currentShapePainterStrategy.endDrag(); } clearStrategies(); desktop.repaint(); } private void notifyDragSourceDragComplete(boolean isDropped){ if (dockableDragSource != null){ dockableDragSource.endDragComponent(isDropped); } } public void mouseDragged(MouseEvent e) { if (! isDragAndDropEnabled()){ // disable dnd right now ignoreDrag = true; } if (ignoreDrag) { return; } else if (startDrag){ startDrag = false; processDragGestureStart(e); } else { processMouseDragged(e); } } private void processDragGestureStart(MouseEvent e){ DockableDragSource dragSource = ( (DockableDragSource) e.getSource()); this.dragPoint = SwingUtilities.convertPoint( (Component) e.getSource(), e.getPoint(), desktop); this.dropShape = null; this.dockableDragSource = null; this.startDragPoint = e.getPoint(); if (dragSource.startDragComponent(startDragPoint)) { this.dockableDragSource = dragSource; getShapePainter(e.getComponent(), dragSource).startDrag(dragSource); this.startDragPoint = new Point(dragPoint); // same coordinate system for future use processMouseDragged(e); // forward the event to the actual processing } else { // drag rejected this.ignoreDrag = true; } } private boolean isDragAndDropEnabled(){ return UIManager.getBoolean("DragControler.isDragAndDropEnabled"); } private void processMouseDragged(MouseEvent e){ Component dragged = (Component) e.getSource(); DockableDragSource dragSource = ( (DockableDragSource) e.getSource()); this.dragPoint = SwingUtilities.convertPoint( (Component) e.getSource(), e.getPoint(), desktop); // if (dockableDragSource == null){ // return; // safety net : there seems to be a case where dockableDragSource can be null on // // mac os (probable cause : a missing mousepressed/released event) // } // continue drag UnderMouseInfo umInfo = findComponentUnderMouse(e); Component underMouse = umInfo.underMouse; Component underMouseNullDesktop = null; DockingDesktop targetDesktop = umInfo.desktop;//findNearestNestedDesktop(umInfo.underMouse); if (targetDesktop == null){ underMouseNullDesktop = findDropReceiverOutsideDesktop(underMouseNullDesktop, e); } ShapePainterStrategy shapePainterStrategy = getShapePainter(underMouse, dragSource); if (dragPoint == null || startDragPoint == null){ // 2006/03/16 // safety net again : a bug has been submitted reagrding a NPE and I can't reproduce it ignoreDrag = true; return; } if (targetDesktop == null){ //2006/09/11 // deny drag gesture when desktops aren't compatible if (underMouseNullDesktop != null){ // we've found a dock drop receiver // we send a really simple event DockDragEvent event = new DockDragEvent(desktop, dragSource, e); ((DockDropReceiver)underMouseNullDesktop).processDockableDrag(event); } // finished shapePainterStrategy.showStopDragCursor(); setDropShape(null, shapePainterStrategy); return; } else if (targetDesktop.getContext() != desktop.getContext()){ //2006/09/11 // deny drag gesture when desktops aren't compatible shapePainterStrategy.showStopDragCursor(); setDropShape(null, shapePainterStrategy); return; } int dx = dragPoint.x - startDragPoint.x; int dy = dragPoint.y - startDragPoint.y; if (Math.abs(dx) < 20 && Math.abs(dy) < 10){ // deny drag gesture when too near from start point 2005/11/15 shapePainterStrategy.showStopDragCursor(); setDropShape(null, shapePainterStrategy); return; } // 2005/11/08 support for full height/width docking DockingPanel dp = targetDesktop.getDockingPanel(); Insets i = targetDesktop.getDockingPanelInsets(); Rectangle deskBounds = new Rectangle(i.left, i.top, targetDesktop.getWidth() - i.left - i.right, targetDesktop.getHeight() - i.top - i.bottom); Rectangle innerBounds = new Rectangle(deskBounds); innerBounds.x += 5; innerBounds.y += 5; innerBounds.width -= 10; innerBounds.height -= 10; if (deskBounds.contains(dragPoint) && ! innerBounds.contains(dragPoint) && underMouse != null && targetDesktop.isAncestorOf(underMouse)){ // at less than 5 pixels from a border, promote DockingPanel as the receiver underMouse = dp; } // go up the hierarchy until we find a component that can receive a drop while (underMouse != null && underMouse != targetDesktop && ! (underMouse instanceof DockDropReceiver)) { underMouse = underMouse.getParent(); } umInfo.underMouse = underMouse; // resync if (underMouse == null){// || isAncestorOf(dockableDragSource.getDockableContainer(), underMouse)){ // it's not possible to drop a parent on one of its children // so we're goind to try and detach it if (underMouse instanceof DockDropReceiver){ // but we still have to use the reference on drop receiver to display a floating drag shape this.dropReceiver = (DockDropReceiver) underMouse; } DragProcess process = new DragProcess(dockableDragSource, umInfo); if (process.canDockableBeDetached() && process.checkAndDetachDockable(shapePainterStrategy)){ // this method manages the detachement } else { // refused (vetoed) shapePainterStrategy.showStopDragCursor(); setDropShape(null, shapePainterStrategy); } } else if (underMouse instanceof DockDropReceiver && e.isControlDown()) { //2005/11/08 HOT SWAP FUNCTION processHotSwap(underMouse, dragged, shapePainterStrategy, false); } else if (underMouse instanceof DockDropReceiver) { // loop if it returns null DragProcess process = new DragProcess(dockableDragSource, umInfo); DockDragEvent event = process.findAcceptableEvent(e); // will it cause a state change ? // a state change occur when switching between CLOSED, HIDDEN, and DOCKED // in this context, the drag event can only be generated by a hidden dockable // (if there is a way to drag its button) or an already docked dockable (no state change) if (event.isDragAccepted() && process.isDockingActionAccepted()) { shapePainterStrategy.showDragCursor(); setDropShape(event.getDropShape(), shapePainterStrategy); } else if (process.canDockableBeDetached() && process.checkAndDetachDockable(shapePainterStrategy)){ // detach done by the "if" } else { event.rejectDrag(); // vetoed by listeners shapePainterStrategy.showStopDragCursor(); setDropShape(null, shapePainterStrategy); } } else {// not above a drop receiver, might be detachable DragProcess process = new DragProcess(dockableDragSource, umInfo); if (process.canDockableBeDetached() && process.checkAndDetachDockable(shapePainterStrategy)){ // this method manages the detachement } else { // refused (vetoed) shapePainterStrategy.showStopDragCursor(); setDropShape(null, shapePainterStrategy); } } } /** Allow hot swappping of two top level dockable containers (during drag) */ private void processHotSwap(Component underMouse, Component dragged, ShapePainterStrategy shapePainterStrategy, boolean drop){ //2005/11/08 /* This whole method should be reworked to allow hooking a DockingActionEvent subclass * to process hotswapping. * This also means we have to get rid of these "Component" and rely on DockableContainers * instead (which will allow us to properly track dockable state changes) */ // --------------------- // shortcut : if the underMouse component doesn't belong to a DockingPanel, we // just cancel the hot swap operation // explanation : hotswap between DOCKED and FLOATING whould otherwise mean // swapping dockable states, and this will not be allowed until a further release Component topLevel = underMouse; while (topLevel != null && !(topLevel instanceof DockingPanel) ){ topLevel = topLevel.getParent(); } if (topLevel == null){ // doesn't belong to a docking panel == not DOCKED if (! drop){ shapePainterStrategy.showStopDragCursor(); setDropShape(null, shapePainterStrategy); } return; } // --------------------- // to implement the "hot swap" we need to find a top level dockable container // (whose parent should be SplitContainer). while (underMouse != null && !(underMouse.getParent() instanceof SplitContainer)){ underMouse = underMouse.getParent(); } if (underMouse != null){ Component splitChild = dragged; while (splitChild != null && !(splitChild.getParent()instanceof SplitContainer) ){ splitChild = splitChild.getParent(); } if (splitChild != null && splitChild != underMouse && underMouse instanceof DockDropReceiver){// this one should always be true (although as it depends on implementation details, I prefer to keep it safe) // ok we've found a suitable swap pattern if (drop){ DockingUtilities.updateResizeWeights(desktop.getDockingPanel()); DockingUtilities.swapComponents(splitChild, underMouse); DockingUtilities.updateResizeWeights(desktop.getDockingPanel()); } else { shapePainterStrategy.showSwapDragCursor(); Rectangle bounds = underMouse.getBounds(); Rectangle2D shape = new Rectangle2D.Float(0, 0, bounds.width, bounds.height); this.dropReceiver = (DockDropReceiver) underMouse; setDropShape(shape, shapePainterStrategy); } } else { // couldn't find a suitable component if (!drop){ shapePainterStrategy.showStopDragCursor(); setDropShape(null, shapePainterStrategy); } } } else { // couldn't find a suitable component if (! drop){ shapePainterStrategy.showStopDragCursor(); setDropShape(null, shapePainterStrategy); } } } private void setDropShape(Shape shape, ShapePainterStrategy shapePainterStrategy){ setDropShape(shape, shapePainterStrategy, false); } private void setDropShape(Shape shape, ShapePainterStrategy shapePainterStrategy, boolean floating){ if (dropShape == null){ if (shape != null){ this.dropShape = shape; this.isFloatingShape = floating; shapePainterStrategy.repaint(); } } else { if (shape != null){ if (!dropShape.equals(shape)){ this.dropShape = shape; this.isFloatingShape = floating; shapePainterStrategy.repaint(); } } else { this.dropShape = shape; this.isFloatingShape = floating; shapePainterStrategy.repaint(); } } } /** Checks if a component is an ancestor of another one */ private boolean isAncestorOf(Component probableAncestor, Component child){ while (child != null && child != probableAncestor){ child = child.getParent(); } return child == probableAncestor; } public void mouseMoved(MouseEvent e) { } /** Returns information about the component right under the mouse (including other owned windows)*/ private UnderMouseInfo findComponentUnderMouse(MouseEvent e){ // are we above an insertion point ? Point p = new Point(e.getPoint()); SwingUtilities.convertPointToScreen(p, e.getComponent()); UnderMouseInfo umInfo = new UnderMouseInfo(); //Component underMouse = null; // iterate through the owned windows (might be floatables) Window w = SwingUtilities.getWindowAncestor(desktop); Window [] children = w.getOwnedWindows(); for (int i=0; i < children.length; i++){ if (children[i] instanceof FloatingDockableContainer && children[i].isVisible()){ Window wChild = (Window) children[i]; // assumed by the FloatingDockableContainer interface Rectangle bounds = wChild.getBounds(); if (bounds.contains(p)){ // an owned window is on top of the desktop, at current mouse position // we have to try and find a dockable into this window Point p2 = SwingUtilities.convertPoint(e.getComponent(), e.getPoint(), wChild); Container contentPane = (wChild instanceof JDialog) ? ((JDialog)wChild).getContentPane() : ((JFrame)wChild).getContentPane(); umInfo.underMouse = findComponentAt(contentPane, p2.x, p2.y); // bypass the glasspane umInfo.desktop = desktop; } } } if (umInfo.underMouse == null && desktop.getContext().getDesktopList().size() > 1){ // now look for other desktops sharing the same context // and select the top most window at current mouse location DockingContext ctx = desktop.getContext(); ArrayList desktops = ctx.getDesktopList(); // create a list of unique windows ArrayList windows = new ArrayList(); for (int i=0; i < desktops.size(); i++){ DockingDesktop desk = (DockingDesktop) desktops.get(i); Window deskWin = SwingUtilities.getWindowAncestor(desk); if (deskWin != null && !windows.contains(deskWin)){ // intersection with mouse ? if (deskWin.getBounds().contains(p)){ windows.add(deskWin); } } } // now we have an unordered list of windows all intersecting our point : find which one // is above Window topWindow = null; Iterator it = ctx.getOwnedWindowActionOrder().iterator(); while (it.hasNext()){ Window win = (Window) it.next(); if (windows.contains(win)){ topWindow = win; break; } } if (topWindow != null){ Point p2 = SwingUtilities.convertPoint(e.getComponent(), e.getPoint(), topWindow); Container contentPane = (topWindow instanceof JDialog) ? ((JDialog)topWindow).getContentPane() : ((JFrame)topWindow).getContentPane(); umInfo.underMouse = findComponentAt(contentPane, p2.x, p2.y); // bypass the glasspane // now find the desktop associated to the component (there might be more than 1 desktop / window) // we have to walk up the hierarchy Component c = umInfo.underMouse; while ( c != null){ if (c instanceof DockingDesktop){ umInfo.desktop = (DockingDesktop) c; break; } else { c = c.getParent(); } } } // @todo : also check for floating windows belonging to these other desktops } if (umInfo.underMouse == null){ umInfo.underMouse = findComponentAt(desktop, dragPoint.x, dragPoint.y); umInfo.desktop = desktop; } return umInfo; } /** find the top most component of this container */ private Component findComponentAt(Container container, int x, int y){ if (isLightWeight){ return container.findComponentAt(x, y); } else { /* couldn't use the standard Container.findComponentAt(int, int) method for our * heavyweight support (we need more control on the heavyweight components to skip). * So we use a custom search instead */ return findComponentAtForHeavy(container, x, y); } } /** find the top most component of this container. used only for heavyweight * support */ private Component findComponentAtForHeavy(Container container, int x, int y){ Rectangle bounds = new Rectangle(); int count = container.getComponentCount(); //ShapePainterStrategy shapePainterStrategy = getShapePainter(container, null); for(int i=0; i < count; i ++){ Component child = container.getComponent(i); if (child.isVisible()){ child.getBounds(bounds); if (bounds.contains(x, y)){ if (child instanceof Container){ // recursive Component found = findComponentAtForHeavy((Container)child, x-bounds.x, y-bounds.y); if (found != null){ return found; } else { return child; } } else if (!(child instanceof HeavyShape ||child instanceof HeavyLabel)){ // skip our dedicated components for heavyweight support return child; // } else if (child != shapePainterStrategy.heavyShape && // child != shapePainterStrategy.heavyShape.label){ // // skip our dedicated components for heavyweight support // return child; } } } } return null; } private HashMap shapePainters = new HashMap(); // window / shapePainterStategy /** searches the best shapePainter */ private ShapePainterStrategy getShapePainter(Component comp, DockableDragSource source){ if (comp == null){ comp = desktop; } Window w = SwingUtilities.getWindowAncestor(comp); ShapePainterStrategy newStrategy = (ShapePainterStrategy)shapePainters.get(w); if (newStrategy == null){ newStrategy = new ShapePainterStrategy(w); shapePainters.put(w, newStrategy); if (currentShapePainterStrategy != null){ currentShapePainterStrategy.endDrag(); } currentShapePainterStrategy = newStrategy; newStrategy.startDrag(source); return newStrategy; } else if (newStrategy == currentShapePainterStrategy){ return newStrategy; } else { // newstrategy not null and != currentStategy currentShapePainterStrategy.endDrag(); currentShapePainterStrategy = newStrategy; newStrategy.startDrag(source); return newStrategy; } } /** clears the shape painters cache to avoid keeping references of old windows */ private void clearStrategies(){ Window w = SwingUtilities.getWindowAncestor(desktop); Window []owned = w.getOwnedWindows(); for (int i=0; i < owned.length; i++){ shapePainters.remove(w); } } /** Looks for nested desktops, and selects the one which is near from underMouse * or null (but it shouldn't occur) */ private DockingDesktop findNearestNestedDesktop(Component underMouse) { if (underMouse == null){ return null; } Container parent = underMouse.getParent(); while (parent != null && !(parent instanceof DockingDesktop)){ parent = parent.getParent(); } if (parent instanceof DockingDesktop){ return (DockingDesktop) parent; } else { return null; } } /** searches for a dockDropReceiver when mouse is outside a docking desktop */ private Component findDropReceiverOutsideDesktop(Component underMouse, MouseEvent e) { // there's a side case we have to manage : when a DockDropReceiver has been // installed *outside* a desktop (this is desired when you want to // listen to drag and drop events (e.g. for a workspace switcher) // note : the event will be sent to the DockDropReceiver, but just for Drag // (ignored as a drop) // go up the hierarchy until we find a component that can receive a drop // currently this works only for the desktop's own window Container base = null; Window w = SwingUtilities.getWindowAncestor(desktop); if (w instanceof JFrame){ base = ((JFrame)w).getContentPane(); } else if (w instanceof JDialog){ base = ((JDialog)w).getContentPane(); } if (base !=null){ Point pw = SwingUtilities.convertPoint((Component) e.getSource(), e.getPoint(), base); underMouse = findComponentAt(base, pw.x, pw.y); while (underMouse != null && ! (underMouse instanceof DockDropReceiver)) { underMouse = underMouse.getParent(); } } return underMouse; } // ----------------------------------------------------------------------------------------------------------- // --------------------------------- you don't want to look at the code underneath this line... -------------- // ----------------------------------------------------------------------------------------------------------- // I'll rewrite it entirely soon as i'm not pleased with it (much too complex) /** This class holds implementation strategies of shapes painting. *

* As painting is different when pure Swing is used (glasspane) and * heavyweight components are mixed in (glasspane + canvas). */ private class ShapePainterStrategy { private GlassPane dragGlassPane = new GlassPane(); private Component oldGlassPane = null; private boolean oldGlassPaneVisible = false; private Window window = null; private boolean isDragStarted = false; // heavyweight support private HeavyShape heavyShape; // instanciated only when heavyweight suport is enabled /*public ShapePainterStrategy(){ if (! isLightWeight){ dragGlassPane.setPaintShapes(false); heavyShape = new HeavyShape(); } }*/ public ShapePainterStrategy(Window window){ this.window = window; if (! isLightWeight){ dragGlassPane.setPaintShapes(false); heavyShape = new HeavyShape(); } } /** show the drag cursor */ public void showDragCursor(){ dragGlassPane.showDragCursor(); if (! isLightWeight){ heavyShape.setCursor(dragGlassPane.getCursor()); } } /** show the stop-drag cursor (drag not enabled)*/ public void showStopDragCursor(){ dragGlassPane.showStopDragCursor(); if (! isLightWeight){ heavyShape.setCursor(dragGlassPane.getCursor()); // heavyShape.setVisible(false); } } /** show the stop-drag cursor (drag not enabled)*/ public void showSwapDragCursor(){ dragGlassPane.showSwapDragCursor(); if (! isLightWeight){ heavyShape.setCursor(dragGlassPane.getCursor()); // heavyShape.setVisible(false); } } /** show the float (detached) cursor */ public void showFloatCursor(){ dragGlassPane.showFloatCursor(); if (! isLightWeight){ heavyShape.setCursor(dragGlassPane.getCursor()); } } public void repaint(){ /* this is a hack that will be refactored : we post a repaint when there is * a need to show a drag shape */ if (isLightWeight){ dragGlassPane.repaint(); } else { // heavy if (dropShape != null){ heavyShape.moveToShape(dropShape); // adjust to the shape before repainting } else if (heavyShape.isVisible()){ heavyShape.setVisible(false); } } } public void startDrag(DockableDragSource source){ if (isDragStarted || source == null){ return; } Window aboveWindow = this.window; isDragStarted = true; if (! isLightWeight){ if (heavyShape.getParent() == null){ // first use of the heavyshapes components if (aboveWindow instanceof JFrame) { JFrame fr = (JFrame) aboveWindow; fr.getLayeredPane().add(heavyShape, JLayeredPane.DRAG_LAYER); heavyShape.validate(); fr.getLayeredPane().add(heavyShape.label, JLayeredPane.DRAG_LAYER); } else if (aboveWindow instanceof JDialog) { JDialog dlg = (JDialog) aboveWindow; dlg.getLayeredPane().add(heavyShape, JLayeredPane.DRAG_LAYER); heavyShape.validate(); dlg.getLayeredPane().add(heavyShape.label, JLayeredPane.DRAG_LAYER); } heavyShape.setZOrder(); } heavyShape.label.setName(source.getDockable().getDockKey().getName()); // take a snapshot of the frame... ugly trick, but couldn't find anything better ! heavyShape.startDrag(); } if (aboveWindow instanceof JFrame) { oldGlassPane = ( (JFrame) aboveWindow).getGlassPane(); oldGlassPaneVisible = oldGlassPane.isVisible(); ( (JFrame) aboveWindow).setGlassPane(dragGlassPane); dragGlassPane.setVisible(true); } else if (aboveWindow instanceof JDialog) { oldGlassPane = ( (JDialog) aboveWindow).getGlassPane(); oldGlassPaneVisible = oldGlassPane.isVisible(); ( (JDialog) aboveWindow).setGlassPane(dragGlassPane); dragGlassPane.setVisible(true); } } public void endDrag(){ if (! isLightWeight){ heavyShape.setVisible(false); } Window aboveWindow = this.window;//SwingUtilities.getWindowAncestor(desktop); if (aboveWindow instanceof JFrame) { ( (JFrame) aboveWindow).setGlassPane(oldGlassPane); } else if (aboveWindow instanceof JDialog) { ( (JDialog) aboveWindow).setGlassPane(oldGlassPane); } oldGlassPane.setVisible(oldGlassPaneVisible); isDragStarted = false; } } /** A glasspane use to paint drag / drop shape on top of the desktop */ class GlassPane extends JComponent { Cursor stopDragCursor, dragCursor, floatCursor, swapDragCursor; Color innerColor = new Color(64,64,64, 64); Color textColor = Color.WHITE; Color textFillColor = new Color(32, 32,32, 128); Color textBorderColor = new Color(64, 64, 64); boolean paintShapes = true; ShapeLabelPainter labelPainter = new ShapeLabelPainter(); ShapeOutlinePainter outlinePainer = new ShapeOutlinePainter(); GlassPane() { addMouseListener(new MouseAdapter() {}); // grab events addMouseMotionListener(new MouseMotionAdapter() {}); showDragCursor(); } /** Enables or disables shape painting */ public void setPaintShapes(boolean paintShapes){ this.paintShapes = paintShapes; } public void paintComponent(Graphics g) { if (paintShapes){ Graphics2D g2 = (Graphics2D) g; if (dropShape != null) { Shape s = dropShape; Point p = SwingUtilities.convertPoint( (Component) dropReceiver, 0, 0, this); Shape s2 = AffineTransform.getTranslateInstance(p.x, p.y).createTransformedShape(s); outlinePainer.paintShape(g2, s2); labelPainter.paintLabel(g2, s2, dockableDragSource.getDockable().getDockKey().getName()); } } } public void showStopDragCursor() { if (stopDragCursor == null) { Image stopDragImage = (Image)UIManager.get("DragControler.stopDragCursor"); //2005/11/01 stopDragCursor = Toolkit.getDefaultToolkit().createCustomCursor( stopDragImage , new Point(16, 16), "stopdragcursor"); } setCursor(stopDragCursor); } public void showSwapDragCursor() { if (swapDragCursor == null) { Image swapDragImage = (Image)UIManager.get("DragControler.swapDragCursor"); //2005/11/01 swapDragCursor = Toolkit.getDefaultToolkit().createCustomCursor( swapDragImage , new Point(16, 16), "swapdragcursor"); } setCursor(swapDragCursor); } public void showFloatCursor() { if (floatCursor == null) { Image floatImage = (Image)UIManager.get("DragControler.detachCursor"); //2005/11/01 floatCursor = Toolkit.getDefaultToolkit().createCustomCursor( floatImage, new Point(16, 16), "floatcursor" ); } setCursor(floatCursor); } public void showDragCursor() { if (dragCursor == null) { Image dragImage = (Image)UIManager.get("DragControler.dragCursor"); //2005/11/01 dragCursor = Toolkit.getDefaultToolkit().createCustomCursor(dragImage, new Point(16, 16), "dragcursor" ); } setCursor(dragCursor); } } /** heavyweight component used to paint shapes on top of heavyweight components */ private class HeavyShape extends Canvas { private Rectangle cachedShapeBounds; private BufferedImage desktopImage; // used for heavyweight painting private Image subImage; private Rectangle subImageBounds; private ShapeOutlinePainter outlinePainter = new ShapeOutlinePainter(); private HeavyLabel label = new HeavyLabel(); public HeavyShape(){ setEnabled(false); // don't override the glaspane cursor } public void setZOrder(){ // jdk1.5 only try { //desktop.setComponentZOrder(this, -1); // on top Method m = Container.class.getMethod("setComponentZOrder", new Class[]{ Component.class, int.class}); m.invoke(getParent(), new Object[]{this, new Integer(0)}); } catch (Exception ignore){ } label.setZOrder(); } private void startDrag(){ Container parent = getParent(); if (paintBackgroundUnderDragRect ){ // 2007/02/27 if (desktopImage == null || (desktopImage.getWidth() != parent.getWidth()) || (desktopImage.getHeight() != parent.getHeight())){ desktopImage = (BufferedImage)parent.createImage(parent.getWidth(), parent.getHeight()); subImage = null; } Graphics g = desktopImage.getGraphics(); parent.paint(g); g.dispose(); } } public void paint(Graphics g){ if (dropShape != null) { Point p = SwingUtilities.convertPoint( (Component) dropReceiver, 0, 0, getParent()); Rectangle r = dropShape.getBounds(); int shapeX = r.x, shapeY = r.y; if (paintBackgroundUnderDragRect){ r.x += p.x; r.y += p.y; r.width +=2; // stroked shape (+3 pixels, centered) r.height +=2; if (r.x + r.width > desktopImage.getWidth()){ r.width = desktopImage.getWidth() - r.x; } if (r.y + r.height > desktopImage.getHeight()){ r.height = desktopImage.getHeight() - r.y; } if (subImage == null || !r.equals(subImageBounds)){ subImageBounds = r; subImage = desktopImage.getSubimage(r.x, r.y, r.width, r.height); } g.drawImage(subImage, 0,0, null); } Shape s = AffineTransform.getTranslateInstance(-shapeX, -shapeY).createTransformedShape(dropShape); Graphics2D g2 = (Graphics2D) g; outlinePainter.paintShape(g2, s); } } public void setVisible(boolean visible){ super.setVisible(visible); label.setVisible(visible); } public void setCursor(Cursor cursor){ super.setCursor(cursor); label.setCursor(cursor); } /** moves and resizes the canvas to the position of the drop shape */ public void moveToShape(Shape newShape){ setVisible(true); Shape s = dropShape; Container container = getParent(); Point p = SwingUtilities.convertPoint( (Component) dropReceiver, 0, 0, container); Rectangle r = dropShape.getBounds(); r.x += p.x; r.y += p.y; r.width +=2; // shape has stroke(3), so we must extend it a little bit r.height +=2; if (r.x + r.width > container.getWidth()){ // check extend not out of bounds r.width = container.getWidth() - r.x; } if (r.y + r.height > container.getHeight()){ r.height = container.getHeight() - r.y; } if (! r.equals(cachedShapeBounds)){ setBounds(r); cachedShapeBounds = r; label.moveToCenter(r); } } } private class HeavyLabel extends Canvas { private Color textColor = Color.WHITE; private Color textFillColor = new Color(128,128,128); private Color textBorderColor = new Color(64, 64, 64); private String name; private Icon icon; public HeavyLabel(){ setEnabled(false); // don't override the glaspane cursor } public void setZOrder(){ // jdk1.5 only (but we compile with source=1.4) try { //desktop.setComponentZOrder(this, -2); // on top of heavy panel Method m = Container.class.getMethod("setComponentZOrder", new Class[]{ Component.class, int.class}); m.invoke(getParent(), new Object[]{this, new Integer(0)}); } catch (Exception ignore){ ignore.printStackTrace(); } } public void setName(String name){ this.name = name; } public void setIcon(Icon icon){ this.icon = icon; } public void moveToCenter(Rectangle shapeBounds){ Font f = getFont(); if (f != null){ FontMetrics fm = getFontMetrics(f); int w = fm.stringWidth(name) + 10; int h = fm.getHeight() + 5; setBounds(shapeBounds.x + shapeBounds.width/2 - w/2, shapeBounds.y + shapeBounds.height/2 - h/2, w, h); } } public void paint(Graphics g){ FontMetrics fm = g.getFontMetrics(); int w = fm.stringWidth(name); int h = fm.getHeight(); g.setColor(textFillColor); g.fillRect(0,0, getWidth(), getHeight()); g.setColor(textBorderColor); g.drawRect(0,0, getWidth()-1, getHeight()-1); g.setColor(textColor); g.drawString(name, getWidth()/2-w/2,getHeight()/2 + h/2); } } /** the object responsible for painting the shape outline */ private class ShapeOutlinePainter { private Color innerColor = new Color(64,64,64); public void paintShape(Graphics2D g2, Shape s){ Composite old = g2.getComposite(); g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.25f)); g2.setStroke(new BasicStroke(3)); g2.setColor(innerColor); g2.fill(s); g2.setComposite(old); g2.setColor(Color.DARK_GRAY); g2.draw(s); } } /** the object responsible for painting the shape label */ private class ShapeLabelPainter { private Color textColor = Color.WHITE; private Color textFillColor = new Color(32, 32,32, 128); // private Color textFillColor = new Color(128, 128,128); private Color textBorderColor = new Color(64, 64, 64); public void paintLabel(Graphics2D g2, Shape s, String name){ Rectangle bounds = s.getBounds(); FontMetrics fm = g2.getFontMetrics(); int w = fm.stringWidth(name); g2.setColor(textFillColor); int bx, by; if (isFloatingShape){ bx = bounds.x + bounds.width/2 - w/2 ; by = bounds.y + bounds.height/2 - fm.getHeight()/2; } else { bx = 4*((bounds.x + bounds.width/2 - w/2)/4) ; // 2005/11/01 small hack to overcome small drifts of the label // (for example when used on a tabbedpane and when the selected tab is // one or two pixels bigger than a non selected tab. // just snapping it with a 4*4 grid avoid those glitches (without changing // too much the shapes algorithm). by = 4*((bounds.y + bounds.height/2 - fm.getHeight()/2) / 4); } g2.fillRect(bx- 5, by, w +10, fm.getHeight()); g2.setStroke(new BasicStroke(1)); g2.setColor(textBorderColor); g2.drawRect(bx- 5, by, w +10, fm.getHeight()); g2.setColor(textColor); g2.drawString(name, bx, by + fm.getAscent()); } } /** A component that encapsulates the drag process (manages vetoable events, floatability..) */ private class DragProcess { DockableDragSource source; UnderMouseInfo umInfo; boolean stateChange = false; int futureState; DockingActionEvent dockingActionEvent; DragProcess(DockableDragSource source, UnderMouseInfo umInfo){ this.source = source; this.umInfo = umInfo; this.futureState = DockingUtilities.getDockableStateFromHierarchy(umInfo.underMouse); } /** search until a drag event is accepted or rejected (not delegated) */ public DockDragEvent findAcceptableEvent(MouseEvent e){ DockDragEvent event; boolean loop = false; Component underMouse = umInfo.underMouse; do { dropReceiver = (DockDropReceiver) underMouse; MouseEvent convertMouse = SwingUtilities.convertMouseEvent( (Component) e.getSource(), e, underMouse); DockableDragSource dragSource = ( (DockableDragSource) e.getSource()); event = new DockDragEvent(umInfo.desktop, dragSource, convertMouse); dropReceiver.processDockableDrag(event); if (event.isDragAccepted()) { } else if (event.isDragDelegated()) { // find another dropper underMouse = underMouse.getParent(); while (underMouse != null && underMouse != umInfo.desktop && ! (underMouse instanceof DockDropReceiver)) { underMouse = underMouse.getParent(); } } if (event.isDragAccepted()) { loop = false; } else if (event.isDragDelegated() && underMouse instanceof DockDropReceiver) { loop = true; } else { loop = false; } } while (loop); if (event != null){ this.dockingActionEvent = event.getDockingAction(); umInfo.underMouse = underMouse; // 2007/01/06 } return event; } /** verifies if the dockable(s) movement will not be vetoed by listeners * */ public boolean isDockingActionAccepted(){ if (source.getDockableContainer() instanceof TabbedDockableContainer){ // here we're dragging a whole tabbed pane TabbedDockableContainer tdc = (TabbedDockableContainer) source.getDockableContainer(); for (int i=0; i < tdc.getTabCount(); i++){ Dockable d = tdc.getDockableAt(i); if (! isSingleDockingActionAccepted(d)){ return false; } } return true; } else { return isSingleDockingActionAccepted(source.getDockable()); } } /** internal method for a single dockable */ private boolean isSingleDockingActionAccepted(Dockable dockable){ DockableState currentState = umInfo.desktop.getDockableState(dockable); // will it cause a state change ? // a state change occur when switching between CLOSED, HIDDEN, and DOCKED // in this context, the drag event can only be generated by a hidden dockable // (if there is a way to drag its button) or an already docked dockable (no state change) if (currentState.getState() != futureState) { // state cannot be null this.stateChange = true; DockableState newState = new DockableState(umInfo.desktop, dockable , futureState); DockableStateWillChangeEvent dscwEvent = new DockableStateWillChangeEvent(currentState, newState); if (!desktop.getContext().fireDockableStateWillChange(dscwEvent)) { return false; } } if (dockingActionEvent instanceof DockingActionDockableEvent){ DockingActionDockableEvent dde = (DockingActionDockableEvent) dockingActionEvent; // also check for DockingActionEvents if (dde.getDockable() == dockable){ return desktop.getContext().fireAcceptDockingAction(dockingActionEvent); } else { // multiple dockable moved at the same time (tabs) : we create copies // of the original DockingActionEvent // @todo : see if we couldn't create a new type of action instead DockingActionDockableEvent dae = (DockingActionDockableEvent) dde.clone(); dae.setDockable(dockable); return desktop.getContext().fireAcceptDockingAction(dae); } } else if (dockingActionEvent instanceof DockingActionSplitDockableContainerEvent){ // we're dragging a full tab dockable around : accept it always @todo check this return true; } else { throw new RuntimeException("unmanaged docking action " + dockingActionEvent); } } /** check if a dockable can be detached from the desktop */ public boolean canDockableBeDetached(){ if (source.getDockableContainer() instanceof TabbedDockableContainer){ // here we're dragging a whole tabbed pane TabbedDockableContainer tdc = (TabbedDockableContainer) source.getDockableContainer(); for (int i=0; i < tdc.getTabCount(); i++){ Dockable d = tdc.getDockableAt(i); if (! canSingleDockableBeDetached(d)){ return false; } } // last check : the tab container must not be itself already detached Dockable any = tdc.getDockableAt(0); if (any.getDockKey().getDockableState() == DockableState.STATE_FLOATING){ //already detached, refuse another detaching return false; } else { return true; } } else { return canSingleDockableBeDetached(source.getDockable()); } } private boolean canSingleDockableBeDetached(Dockable dockable){ /* must not be already detached + floatingenabled + not maximized */ DockKey key = dockable.getDockKey(); if (key.getDockableState() == DockableState.STATE_FLOATING){ if (DockingUtilities.findTabbedDockableContainer(dockable) != null){ return true; } else { return false;// already detached and single } } if ( key.isFloatEnabled()){ if (key.getDockableState() != DockableState.STATE_MAXIMIZED){ /* int dx = dragPoint.x - startDragPoint.x; int dy = dragPoint.y - startDragPoint.y; if (Math.abs(dx) < 20 && Math.abs(dy) < 10){ // deny detach when too near from start point 2005/11/01 return false; } else { return true; }*/ return true; // the test above has been moved up to filter more drag events } else { return false; } } else { return false; } } /** trigers dockableStageWillChangeEvent to allow vetoing the floating */ public boolean checkDockableWillBeDetached(){ if (source.getDockableContainer() instanceof TabbedDockableContainer){ // here we're dragging a whole tabbed pane TabbedDockableContainer tdc = (TabbedDockableContainer) source.getDockableContainer(); for (int i=0; i < tdc.getTabCount(); i++){ Dockable d = tdc.getDockableAt(i); if (! checkSingleDockableWillBeDetached(d)){ return false; } } return true; } else { return checkSingleDockableWillBeDetached(source.getDockable()); } } private boolean checkSingleDockableWillBeDetached(Dockable dockable){ DockableState newState = new DockableState(desktop, dockable, DockableState.STATE_FLOATING); DockableState currentState = desktop.getDockableState(dockable); DockableStateWillChangeEvent dscwEvent = new DockableStateWillChangeEvent(currentState, newState); // if (! desktop.getContext().fireDockableStateWillChange(dscwEvent)){ return false; } else { // also trigger DockingAction DockingActionEvent dae = new DockingActionSimpleStateChangeEvent(desktop, dockable, currentState.getState(), DockableState.STATE_FLOATING); return desktop.getContext().fireAcceptDockingAction(dae); } } public boolean checkAndDetachDockable(ShapePainterStrategy shapePainterStrategy){ if (checkDockableWillBeDetached()){ if (DockingPreferences.isLightWeightUsageEnabled() && paintFloatingDragShape){ Point shapePoint = new Point(dragPoint); SwingUtilities.convertPointToScreen(shapePoint, desktop); if (dropReceiver != null){ // we are above a drop receiver and we can show something SwingUtilities.convertPointFromScreen(shapePoint, (Component)dropReceiver); Dimension dragSize = dockableDragSource.getDockableContainer().getSize(); setDropShape(new Rectangle2D.Float(shapePoint.x,shapePoint.y, dragSize.width, dragSize.height), shapePainterStrategy, true); } else { setDropShape(null, shapePainterStrategy); } } else { setDropShape(null, shapePainterStrategy); } shapePainterStrategy.showFloatCursor(); return true; } else { return false; } } } private class DropProcess extends DragProcess { MouseEvent event; DropProcess(MouseEvent event, DockableDragSource source, UnderMouseInfo umInfo){ super(source, umInfo); this.event = event; } public boolean dropIfPossible(){ MouseEvent convertMouse = SwingUtilities.convertMouseEvent( (Component) event.getSource(), event, umInfo.underMouse); DockDropEvent dropEvent = new DockDropEvent( umInfo.desktop, source, convertMouse); dropReceiver.processDockableDrop(dropEvent); Component underMouse = umInfo.underMouse; if (dropEvent.isDropAccepted()) { if (underMouse instanceof JComponent) { ( (JComponent) underMouse).revalidate(); } else if (underMouse instanceof Component){ underMouse.validate(); underMouse.repaint(); } fireDockingActionEvent(); return true; } else { return false; } } public void fireDockingActionEvent(){ if (source.getDockableContainer() instanceof TabbedDockableContainer){ TabbedDockableContainer tdc = (TabbedDockableContainer) source.getDockableContainer(); for (int i=0; i < tdc.getTabCount(); i++){ Dockable d = tdc.getDockableAt(i); fireSingleDockingActionEvent(tdc.getDockableAt(i)); } } else { fireSingleDockingActionEvent(source.getDockable()); } } private void fireSingleDockingActionEvent(Dockable dockable){ if (stateChange){ DockableState currentState = desktop.getDockableState(dockable); dockable.getDockKey().setDockableState(futureState); dockingContext.fireDockableStateChange(new DockableStateChangeEvent(currentState, new DockableState(desktop, dockable, futureState))); } if (dockingActionEvent instanceof DockingActionDockableEvent){ DockingActionDockableEvent dde = (DockingActionDockableEvent) dockingActionEvent; if (dde.getDockable() == dockable){ dockingContext.fireDockingActionPerformed(dockingActionEvent); } else { DockingActionDockableEvent dae = (DockingActionDockableEvent) dde.clone(); dae.setDockable(dockable); dockingContext.fireDockingActionPerformed(dae); } } else if (dockingActionEvent instanceof DockingActionSplitDockableContainerEvent){ // we're dropping a whole container (currently it is only possible with // a tabbeddockablecontainer // @todo : missing event to fire here } else { throw new RuntimeException("Unmanaged docking action"); } } public void setFloating(Point location){ if (source.getDockableContainer() instanceof TabbedDockableContainer){ desktop.setFloating((TabbedDockableContainer)source.getDockableContainer(), location); } else { Dockable dockable = source.getDockable(); desktop.setFloating(source.getDockable(), true, location); } } } class UnderMouseInfo { DockingDesktop desktop; Component underMouse; } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/FloatingDialog.java0000644000175000017500000004030010573516350025761 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Cursor; import java.awt.Dialog; import java.awt.Dimension; import java.awt.Frame; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Paint; import java.awt.Point; import java.awt.Rectangle; import java.awt.TexturePaint; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.image.BufferedImage; import javax.swing.BorderFactory; import javax.swing.JComponent; import javax.swing.JDialog; import javax.swing.JPanel; import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.border.Border; /** The floating jdialog for floatable dockables. This is the default implementation of * the FloatingDockableContainer interface. * * @author Lilian Chamontin, VLSolutions * @since 2.0 * @update 2005/10/06 Lilian Chamontin : Reworked the layout (added border components) to * have better cursor and resize management and to allow nesting dockables as tabs. * */ public class FloatingDialog extends JDialog implements FloatingDockableContainer { // constants to listen to border drags private static final int DRAG_TOP = 1; private static final int DRAG_LEFT = 2; private static final int DRAG_RIGHT = 4; private static final int DRAG_BOTTOM = 8; /** the drag header height */ protected int titleHeight = 6; private Color controlColor = UIManager.getColor("control"); private Color highlight = UIManager.getColor("controlLtHighlight"); private Color shadow = UIManager.getColor("controlShadow"); private Color activeCaptionColor = UIManager.getColor("activeCaption"); private Color inactiveCaptionColor = UIManager.getColor("inactiveCaption"); private Color activeCaptionBorderColor = UIManager.getColor("activeCaptionBorder"); private Color inactiveCaptionBorderColor = UIManager.getColor("inactiveCaptionBorder"); private Border activeBorder = BorderFactory.createLineBorder(activeCaptionBorderColor); private Border inactiveBorder = BorderFactory.createLineBorder(inactiveCaptionBorderColor); private JComponent title = createTitlePanel(); private Resizer left = new Resizer(); private Resizer right = new Resizer(); private Resizer bottom = new Resizer(); protected DockingDesktop desktop; public FloatingDialog(Dialog parent) { super(parent); init(); } public FloatingDialog(Frame parent){ super(parent); //setIconImage(parent.getIconImage()); init(); } /** initialisation of the title bar */ public void init(){ installDecoration(); installBorders(); installResizers(); addWindowListener(new WindowAdapter(){ public void windowActivated(WindowEvent e){ getRootPane().setBorder(activeBorder); repaint(); } public void windowDeactivated(WindowEvent e){ getRootPane().setBorder(inactiveBorder); repaint(); } }); title.setPreferredSize(new Dimension(10, titleHeight)); getContentPane().add(title, BorderLayout.NORTH); // ResizeListener listener = new ResizeListener(); // addMouseMotionListener(listener); //2005/10/06 // addMouseListener(listener); } /** Installs or not the window decorations on this dialog. *

* uses setUndecorated(booelan) */ public void installDecoration(){ setUndecorated( true ); } /** Creates the component used as a header to drag the window */ public JComponent createTitlePanel(){ return new TitlePanel(); } /** Installs the borders of this dialog and its title header */ public void installBorders(){ Border border = UIManager.getBorder("FloatingDialog.dialogBorder"); Border titleBorder = UIManager.getBorder("FloatingDialog.titleBorder"); title.setBorder(titleBorder); ((JPanel)getContentPane()).setBorder(border); } /** installs the components used for resizing (on left/right/bottom borders) * @since 2.0.1 */ public void installResizers(){ // 2005/10/06 ResizeListener listener = new ResizeListener(); left.addMouseMotionListener(listener); left.addMouseListener(listener); right.addMouseMotionListener(listener); right.addMouseListener(listener); bottom.addMouseMotionListener(listener); bottom.addMouseListener(listener); title.addMouseMotionListener(listener); title.addMouseListener(listener); getContentPane().add(left, BorderLayout.WEST); getContentPane().add(right, BorderLayout.EAST); getContentPane().add(bottom, BorderLayout.SOUTH); Color inactive = UIManager.getColor("inactiveCaption"); left.setBackground(inactive); right.setBackground(inactive); bottom.setBackground(inactive); } public void installDocking(DockingDesktop desktop){ this.desktop = desktop; } public void setInitialDockable(Dockable dockable) { SingleDockableContainer sdc = DockableContainerFactory.getFactory() .createDockableContainer(dockable, DockableContainerFactory.PARENT_DETACHED_WINDOW); sdc.installDocking(desktop); Component comp = (Component) sdc; getContentPane().add(comp); } public void setInitialTabbedDockableContainer(TabbedDockableContainer tdc) { Component comp = (Component) tdc; getContentPane().add(comp); } // utility resizer class private class ResizeListener implements MouseMotionListener, MouseListener { Point lastPoint = null; int dragType = -1; public void mouseDragged( MouseEvent e ) { Rectangle bounds = getBounds(); Dimension d = getSize(); Point p = e.getPoint(); SwingUtilities.convertPointToScreen( p, e.getComponent() ); int dx = p.x - lastPoint.x; int dy = p.y - lastPoint.y; switch (dragType){ case DRAG_TOP: Point loc = getLocation(); setLocation(loc.x + dx, loc.y+dy); break; case DRAG_TOP | DRAG_LEFT: invalidate(); bounds.x += dx; bounds.y += dy; bounds.width -= dx; bounds.height -= dy; setBounds(bounds); validate(); break; case DRAG_TOP | DRAG_RIGHT: invalidate(); bounds.y += dy; bounds.width += dx; bounds.height -= dy; setBounds(bounds); validate(); break; case DRAG_RIGHT: invalidate(); setSize(d.width + dx, d.height); validate(); break; case DRAG_RIGHT | DRAG_BOTTOM: invalidate(); setSize(d.width + dx, d.height+dy); validate(); break; case DRAG_BOTTOM: invalidate(); setSize(d.width, d.height+dy); validate(); break; case DRAG_BOTTOM | DRAG_LEFT: invalidate(); bounds.x += dx; bounds.width -= dx; bounds.height += dy; setBounds(bounds); validate(); break; case DRAG_LEFT: invalidate(); bounds.x += dx; bounds.width -= dx; setBounds(bounds); validate(); break; } lastPoint = p; } public void mouseReleased(MouseEvent e) { dragType = -1; } public void mousePressed(MouseEvent e) { dragType = 0; Point p = SwingUtilities.convertPoint(e.getComponent(), e.getPoint(), getContentPane()); /*if (p.y < 10){ dragType |= DRAG_TOP; } if (p.x < 5){ dragType |= DRAG_LEFT; } if (p.x > getWidth() - 5){ dragType |= DRAG_RIGHT; } if (p.y > getHeight() - 5){ dragType |= DRAG_BOTTOM; }*/ if (p.y < title.getY() + title.getHeight()){ dragType |= DRAG_TOP; } if (p.x < left.getX() + left.getWidth()){ dragType |= DRAG_LEFT; } if (p.x >= right.getX()){//getWidth() - 5){ dragType |= DRAG_RIGHT; } if (p.y >= bottom.getY()){ dragType |= DRAG_BOTTOM; } lastPoint = e.getPoint(); SwingUtilities.convertPointToScreen( lastPoint, e.getComponent() ); } public void mouseExited(MouseEvent e) { } public void mouseEntered(MouseEvent e) { } public void mouseClicked(MouseEvent e) { } public void mouseMoved(MouseEvent e) { Point p = SwingUtilities.convertPoint(e.getComponent(), e.getPoint(), getContentPane()); int dragType = 0; if (p.y < title.getY() + title.getHeight()){ dragType |= DRAG_TOP; } if (p.x < left.getX() + left.getWidth()){ dragType |= DRAG_LEFT; } if (p.x >= right.getX()){//getWidth() - 5){ dragType |= DRAG_RIGHT; } if (p.y >= bottom.getY()){ dragType |= DRAG_BOTTOM; } Cursor c = null; switch (dragType){ case 0: c = Cursor.getDefaultCursor(); break; case DRAG_TOP: c = Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR); break; case DRAG_TOP | DRAG_LEFT: c = Cursor.getPredefinedCursor(Cursor.NW_RESIZE_CURSOR); break; case DRAG_TOP | DRAG_RIGHT: c = Cursor.getPredefinedCursor(Cursor.NE_RESIZE_CURSOR); break; case DRAG_RIGHT: c = Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR); break; case DRAG_RIGHT | DRAG_BOTTOM: c = Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR); break; case DRAG_BOTTOM: c = Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR); break; case DRAG_BOTTOM | DRAG_LEFT: c = Cursor.getPredefinedCursor(Cursor.SW_RESIZE_CURSOR); break; case DRAG_LEFT: c = Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR); break; } if (!e.getComponent().getCursor().equals(c)){ e.getComponent().setCursor(c); } } } /** Class used as a title for dragging the window around */ protected class TitlePanel extends JComponent { public void paintComponent(Graphics g){ // @todo : this will be refactored to plug custom title rendering Color darker, brighter; if (isActive()){ darker = activeCaptionColor; brighter = activeCaptionBorderColor; } else { darker = inactiveCaptionColor; brighter = inactiveCaptionBorderColor; } /* Graphics2D g2 = (Graphics2D) g; Paint paint = g2.getPaint(); GradientPaint gradient = new GradientPaint(0,0, darker, 0, getHeight(), brighter); g2.setPaint(gradient); g2.fillRect(0,0, getWidth(), getHeight()); g2.setPaint(paint); // restore */ Graphics2D g2 = (Graphics2D) g; g2.setColor(darker); g2.fillRect(0,0, getWidth(), getHeight()); int width = 5; int height = 5; BufferedImage image = new BufferedImage(width,height, BufferedImage.TYPE_INT_ARGB); Graphics ig = image.createGraphics(); ig.setColor(darker); ig.fillRect(0,0, width, height); ig.setColor(new Color(1,1,1,0.5f)); ig.fillRect(2,2, 2, 2); ig.setColor(new Color(0,0,0,0.2f)); ig.fillRect(1,1, 2, 2); ig.dispose(); // Create a texture paint from the buffered image Rectangle r = new Rectangle(0, 0, width, height); TexturePaint tp = null; if (tp == null){ tp = new TexturePaint(image, r); } Paint old = g2.getPaint(); g2.setPaint(tp); g2.fillRect(0,0, getWidth(), height); g2.setPaint(old); //g2.setColor(hightLight); //g2.fillRect(0,getHeight()-1, getWidth(), 1); } } protected class Resizer extends JComponent { Resizer(){ setPreferredSize(new Dimension(3,3)); setOpaque(true); } public void paintComponent(Graphics g){ if (isActive()){ g.setColor(activeCaptionColor); } else { g.setColor(inactiveCaptionColor); } g.fillRect(0,0, getWidth(), getHeight()); } } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/FloatingDockableContainer.java0000644000175000017500000000155510573516344030145 0ustar twernertwernerpackage com.vlsolutions.swing.docking; /** The interface describing a Floating window used to display one or more dockables *

* Objects implementing this interface must be instances of JDialog , as the * pack(), setVisible(), setLocation(), dispose() etc. are assumed. * * @author Lilian Chamontin, VLSolutions */ public interface FloatingDockableContainer { /** This install method is invoked before adding the first dockable */ public void installDocking(DockingDesktop desktop); /** adds the initial dockable to this top-level container */ public void setInitialDockable(Dockable dockable); /** adds the initial tabbdeddockablecontainer to this top-level container. * This will happen when drag-n-dropping a whole tab container from the desktop. */ public void setInitialTabbedDockableContainer(TabbedDockableContainer tdc); } vldocking_2.1.4/src/com/vlsolutions/swing/docking/MaximizedComponentReplacer.java0000644000175000017500000000056510573516344030402 0ustar twernertwernerpackage com.vlsolutions.swing.docking; import javax.swing.JComponent; /** A component used to replace the maximized dockable in the dockable container hierarchy *(as long as the dockable is maximized) * * @author Lilian Chamontin, VLSolutions */ class MaximizedComponentReplacer extends JComponent { public MaximizedComponentReplacer() { } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/MaximizedDockView.java0000644000175000017500000001172710573516350026474 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking; import com.vlsolutions.swing.docking.event.DockDragEvent; import com.vlsolutions.swing.docking.event.DockDropEvent; import com.vlsolutions.swing.docking.event.DockEvent; /** A dockView suitable for maximized dockables * * @author Lilian Chamontin, VLSolutions * @update 2007/01/24 Lilian Chamontin : added DnD blocking (maximized components should't support * drag/drop from floating windows) */ public class MaximizedDockView extends DockView { public MaximizedDockView(Dockable dockable) { super(dockable, true); } /** maximized dockable don't support drag and drop */ public void processDockableDrag(DockDragEvent event) { //2007/01/24 event.rejectDrag(); } /** maximized dockable don't support drag and drop */ public void processDockableDrop(DockDropEvent event) { event.rejectDrop(); } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/MaximizedDockViewAsTab.java0000644000175000017500000000543310573516344027407 0ustar twernertwernerpackage com.vlsolutions.swing.docking; import com.vlsolutions.swing.docking.event.DockDragEvent; import com.vlsolutions.swing.docking.event.DockDropEvent; import java.awt.Point; import javax.swing.AbstractAction; import javax.swing.UIManager; /** A maximized view to use with the TabFactory. * * @author Lilian Chamontin, VLSolutions * @see TabFactory * @since 2.1.3 */ public class MaximizedDockViewAsTab extends DockViewAsTab{ public MaximizedDockViewAsTab(Dockable dockable) { super(dockable); } protected void configureMaximizeButton() { if (isRestoreButtonDisplayed){ maximizeSmartIcon.setIcon(UIManager.getIcon("DockViewTitleBar.restore")); maximizeSmartIcon.setPressedIcon(UIManager.getIcon("DockViewTitleBar.restore.pressed")); maximizeSmartIcon.setRolloverIcon(UIManager.getIcon("DockViewTitleBar.restore.rollover")); // add a tooltip maximizeAction.putValue(AbstractAction.SHORT_DESCRIPTION, UIManager.get("DockViewTitleBar.restoreButtonText")); } } protected void configureFloatButton() { isFloatButtonDisplayed = false; } protected void configureHideButton() { isHideButtonDisplayed = false; } protected void configureCloseButton() { isCloseButtonDisplayed = false; } protected TabHeader createTabHeader(){ return new MaximizedTabHeader(); } public void processDockableDrag(DockDragEvent event) { event.rejectDrag(); } public void processDockableDrop(DockDropEvent event) { event.rejectDrop(); } protected class MaximizedTabHeader extends TabHeader { /** {@inheritDoc} */ public boolean startDragComponent(Point p) { // disable DnD for some cases : // - child of a compound dockable, in hidden state // - child of a maximized compund dockable // - maximized dockable Dockable target = getDockable(); int targetState = target.getDockKey().getDockableState(); if (targetState == DockableState.STATE_HIDDEN){ if (DockingUtilities.isChildOfCompoundDockable(target)){ // nested hidden dockables cannot be drag and dropped return false; } } else if (targetState == DockableState.STATE_DOCKED){ boolean isChildOfMaximizedContainer = false; if (desktop != null){ Dockable max = desktop.getMaximizedDockable(); if (max != null && max.getComponent().getParent().isAncestorOf(this)){ isChildOfMaximizedContainer = true; } } if (isChildOfMaximizedContainer){ return false; } } else if (targetState == DockableState.STATE_MAXIMIZED){ return false; } return true; } } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/RelativeDockablePosition.java0000644000175000017500000002775710573516350030050 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking; import javax.swing.*; import java.awt.*; /** This class is an immutable object used to remember the relative positionning * of docked components. *

* x, y, w, h fields are expressed with double values * varying from 0 to 1. *

*

    *
  • x : 0 = left, 1 = right *
  • y : 0 = top, 1 = bottom *
  • w : 0 = no width, 1-x = full remaining width *
  • h : 0 = no height, 1-y = full remaining height *
* *

* Objects of this class are used to reposition a Dockable on the desktop, based * on lazy constraints : As the desktop is a mix of horizontal and vertical * split panes ({@link SplitContainer}) it is not always possible to put a dockable * exactly where you want given a set of x,y, w, and h constraints. * * * @author Lilian Chamontin, vlsolutions. * @version 1.0 * */ public class RelativeDockablePosition { /** convenience field referencing the TOP border of the DockingDesktop */ public static final RelativeDockablePosition TOP = new RelativeDockablePosition(0,0,1, 0.2); /** convenience field referencing the CENTER part of TOP border of the DockingDesktop */ public static final RelativeDockablePosition TOP_CENTER = new RelativeDockablePosition(0.4,0,0.2, 0.2); /** convenience field referencing the TOP-RIGHT corner of the DockingDesktop */ public static final RelativeDockablePosition TOP_RIGHT= new RelativeDockablePosition(0,0,0.2, 0.2); /** convenience field referencing the TOP-LEFT corner of the DockingDesktop */ public static final RelativeDockablePosition TOP_LEFT = new RelativeDockablePosition(0.8,0,0.2, 0.2); /** convenience field referencing the RIGHT border of the DockingDesktop */ public static final RelativeDockablePosition RIGHT = new RelativeDockablePosition(0.8,0,0.2, 1); /** convenience field referencing the CENTER part of the RIGHT border of the DockingDesktop */ public static final RelativeDockablePosition RIGHT_CENTER = new RelativeDockablePosition(0.8,0.4,0.2, 0.2); /** convenience field referencing the TOP-RIGHT corner of the DockingDesktop */ public static final RelativeDockablePosition BOTTOM_RIGHT = new RelativeDockablePosition(0.8,0.8,0.2, 0.2); /** convenience field referencing the BOTTOM border of the DockingDesktop */ public static final RelativeDockablePosition BOTTOM = new RelativeDockablePosition(0,0.8,1, 0.2); /** convenience field referencing the CENTER part of the BOTTOM border of the DockingDesktop */ public static final RelativeDockablePosition BOTTOM_CENTER = new RelativeDockablePosition(0.4,0.8,0.2, 0.2); /** convenience field referencing the TOP-RIGHT corner of the DockingDesktop */ public static final RelativeDockablePosition BOTTOM_LEFT = new RelativeDockablePosition(0,0.8,0.2, 0.2); /** convenience field referencing the LEFT border of the DockingDesktop */ public static final RelativeDockablePosition LEFT = new RelativeDockablePosition(0,0,0.2, 1); /** convenience field referencing the CENTER part of the LEFT border of the DockingDesktop */ public static final RelativeDockablePosition LEFT_CENTER = new RelativeDockablePosition(0,0.4,0.2, 0.2); private double x, y, w; // relative positionning (0-1) of the component in the container /** The container used for relative positioning (can be a top level DockingPanel * or an intermediate CompoundDockingPanel) */ private Container relativeAncestorContainer; private double h; /** @see AnchorConstraints.ANCHOR_TOP (this field is an ORing of possible anchors) and contains * 4 boolean values (TOP, LEFT, BOTTOM, RIGHT) */ private int anchors; /** Construct a RelativeDockablePosition, assigning x, y, w, h values from the * current position of a dockable in its desktop container. *

* This constructor is a convenience for the framework, and should not be * used by API users (thus is package protected visibility). * */ RelativeDockablePosition(Container relativeAncestorContainer, Dockable dockable) { /* (package protected) */ resetRelativePosition(relativeAncestorContainer, dockable); } /** Constructs an empty relative position (all fields are initialized with 0.0 values) */ public RelativeDockablePosition() { } /** Constructs a relative position with given location and size. *

* Please remember that the values must be between 0 and 1, as they designate * relative coordinates position/size. * * @throws IllegalArgumentException if values are not in the given bounds * */ public RelativeDockablePosition(double x, double y, double w, double h) { this (null, x, y, w, h); } /** Constructs a relative position with a given location and size, relative to a container */ public RelativeDockablePosition(Container relativeAncestorContainer, double x, double y, double w, double h) { this.relativeAncestorContainer = relativeAncestorContainer; if (x < 0 || x > 1){ throw new IllegalArgumentException("x is out of bounds [0.0 , 1.0] " + x); } if (y < 0 || y > 1){ throw new IllegalArgumentException("y is out of bounds [0.0 , 1.0] " + y); } if (w < 0 || w > 1){ throw new IllegalArgumentException("w is out of bounds [0.0 , 1.0] " + w); } if (h < 0 || h > 1){ throw new IllegalArgumentException("h is out of bounds [0.0 , 1.0] " + h); } this.x = x; this.y = y; this.w = w; this.h = h; } /** Returns the relative x position of the dockable */ public double getX(){ return x; } /** Returns the relative y position of the dockable */ public double getY(){ return y; } /** Returns the relative width of the dockable */ public double getWidth(){ return w; } /** Returns the relative height of the dockable */ public double getHeight(){ return h; } /** Returns a meaningfull string representation of this RelativeDockablePosition */ public String toString(){ return "RelativePosition [" + x+", " + y +", " + w + ", " + h + ", anchors=" + anchors+"]"; } /** Returns the ancestor container used as a reference for the relative potionning *

This can be a DockingPanel (top level ancestor) or CompoundDockingPanel (intermediate ancestor) */ public Container getRelativeAncestorContainer(){ return relativeAncestorContainer; } /** Returns an integer value representing the anchoring of the dockable relatively to * its ancestor container. *

* For example a dockable at the top left angle of an ancestor container will have an * "anchors" value or : AnchorConstraints.ANCHOR_TOP|AnchorConstraints.ANCHOR_LEFT * @see AnchorConstraints */ public int getAnchors(){ return anchors; } /** Updates the current relative ancestor container and anchor positionning */ public void resetRelativePosition(Container relativeAncestorContainer, Dockable dockable) { this.relativeAncestorContainer = relativeAncestorContainer; DockableContainer dockableContainer = DockingUtilities.findSingleDockableContainer(dockable); if (dockableContainer != null && relativeAncestorContainer != null){ Component c = (Component) dockableContainer; Rectangle converted = SwingUtilities.convertRectangle(c, new Rectangle(0,0, c.getWidth(), c.getHeight()), relativeAncestorContainer); x = converted.x / (float)relativeAncestorContainer.getWidth(); y = converted.y / (float)relativeAncestorContainer.getHeight(); w = converted.width / (float)relativeAncestorContainer.getWidth(); h = converted.height / (float)relativeAncestorContainer.getHeight(); // also set boolean anchors this.anchors = RelativeDockingUtilities.findAnchors(dockable.getComponent(), relativeAncestorContainer); } } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/RelativeDockingUtilities.java0000644000175000017500000022734410573516350030063 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking; import com.vlsolutions.swing.docking.event.DockingActionAddDockableEvent; import com.vlsolutions.swing.docking.event.DockingActionEvent; import com.vlsolutions.swing.docking.event.DockingActionSplitComponentEvent; import java.awt.*; import javax.swing.*; /** This class provides an algorithm for finding (and then inserting) the most suitable place to * show a dockable, based on a relative positionning. * * @author Lilian Chamontin, vlsolutions. * @version 1.0 * @update 2005/10/10 Lilian Chamontin : improved heuristics of resizing (best matching of the appropriate SplitContainer) * @update 2005/10/10 Lilian Chamontin : improved again heuristics of resizing */ class RelativeDockingUtilities { /* package class */ /* This class is an extraction of DockingDesktop - we will enhance (and complexify) * the algorithm later, * and should not mess up with DockingDesktop source code. * * */ private RelativeDockingUtilities() { } /** try to find the best suitable SplitContainer from where insertion will * be done. * */ private static SplitContainer findBestContainer(Container ancestorContainer, RelativeDockablePosition position){ // convert relative positionning to current positionning (depending // on the current size of dockingPanel) int x = (int) (position.getX() * ancestorContainer.getWidth()); int y = (int) (position.getY() * ancestorContainer.getHeight()); int w = (int) (position.getWidth() * ancestorContainer.getWidth()); int h = (int) (position.getHeight() * ancestorContainer.getHeight()); int centerX = x + w / 2; int centerY = y + h / 2; Component centerComp = ancestorContainer.findComponentAt(centerX, centerY); // find the splitcontainer containing centerComp, // and ensure this split is linked to ancestorContainer by a hierarchy of split containers // (to avoid selecting a split inside a sub-container) Component splitComp = centerComp; boolean found = false; while (splitComp != null && splitComp != ancestorContainer && ! found){ splitComp = splitComp.getParent(); if (splitComp instanceof SplitContainer){ // ok we've found a split : now let's check if there's a direct split hierarchy // between this one and the ancestor container Component up = splitComp.getParent(); while (up instanceof SplitContainer){ up = up.getParent(); } if (up == ancestorContainer){ found = true; } } } if (splitComp instanceof SplitContainer) { //2006/09/12 /* Try to find a larger splitcontainer that still fits well * with the position. * for example : * * [1|___2_____] * [1|[3|[4|5]]] * * if we remove "2", what remains is [1|[3|[4|5]]] * and on restoring, the selected split is [4|5], although [3|[4|5]] would be * a much better choice. * * to do that, we try to find the parent with the best "width" and "height" * */ float EPSILON = 0.05f; found = true; while (found && splitComp.getParent() instanceof SplitContainer){ found = false; float widthRatio = splitComp.getWidth() / (float) w; float heightRatio = splitComp.getHeight() / (float) h; SplitContainer parentSplit = (SplitContainer) splitComp.getParent(); float pWidthRatio = parentSplit.getWidth() / (float) w; float pHeightRatio = parentSplit.getHeight() / (float) h; boolean sameOrientation = ((SplitContainer)splitComp).getOrientation() == parentSplit.getOrientation(); if (sameOrientation){ if (parentSplit.getOrientation() == SplitContainer.HORIZONTAL_SPLIT){ // two horizontal, which one has the best width ? if (Math.abs(pWidthRatio-1) < Math.abs(widthRatio-1)){ //parents width is better : we upgrade splitcomp splitComp = splitComp.getParent(); found = true; // loop again } } else { // vertical == same width, is parent height better ? if (Math.abs(pHeightRatio-1) < Math.abs(heightRatio-1)){ //height is better : we upgrade splitcomp splitComp = splitComp.getParent(); found = true; // loop again } } } else { // opposite orientation if (parentSplit.getOrientation() == SplitContainer.HORIZONTAL_SPLIT){ // so split is V and parent is H // has parent a better width ratio ? if (Math.abs(pWidthRatio-1) < Math.abs(widthRatio-1)){ //parents width is better : we upgrade splitcomp splitComp = splitComp.getParent(); found = true; // loop again } } else { if (Math.abs(pHeightRatio-1) < Math.abs(heightRatio-1)){ //height is better : we upgrade splitcomp splitComp = splitComp.getParent(); found = true; // loop again } } } } } /*while (splitComp != null && splitComp != ancestorContainer && ! (splitComp instanceof SplitContainer)) { splitComp = splitComp.getParent(); }*/ if (splitComp instanceof SplitContainer) { // try to enhance the selection when there are global anchors //2005/10/10 // we're now looking for a split container whose anchors would better match // the ones of the dockable position // boolean anchoredTop = Math.abs( y - dockingPanel.getY()) < 5; // boolean anchoredLeft =Math.abs(x - dockingPanel.getX()) < 5; // boolean anchoredBottom = Math.abs(y + h - dockingPanel.getY() - dockingPanel.getHeight()) < 5; // boolean anchoredRight = Math.abs(x + w - dockingPanel.getX() - dockingPanel.getWidth()) < 5; /*boolean anchoredTop = y < 5; //2005/11/08 enhanced ! boolean anchoredLeft = x < 5; boolean anchoredBottom = Math.abs(y + h - ancestorContainer.getHeight()) < 5; boolean anchoredRight = Math.abs(x + w - ancestorContainer.getWidth()) < 5;*/ int anchors = position.getAnchors(); boolean anchoredTop = (anchors & AnchorConstraints.ANCHOR_TOP)>0; boolean anchoredLeft = (anchors & AnchorConstraints.ANCHOR_LEFT)>0; boolean anchoredBottom = (anchors & AnchorConstraints.ANCHOR_BOTTOM)>0; boolean anchoredRight = (anchors & AnchorConstraints.ANCHOR_RIGHT)>0; return findBetterContainer((SplitContainer)splitComp, ancestorContainer, anchoredTop, anchoredLeft, anchoredBottom, anchoredRight); } else { return null; } } /** try to find a SplitContainer up in the hierarchy, satisfying the global anchors */ private static SplitContainer findBetterContainer(SplitContainer split, Container dockingPanel, boolean anchoredTop, boolean anchoredLeft, boolean anchoredBottom, boolean anchoredRight){ // we already have found a splitContainer, but it can be subOptimal in some cases // for instance when we want to anchor a component at the bottom of the container (full width), // and there are two horizontal splits there, we might return the internal split (not full width), // and not the external (full width) one. // this method will try to find a splitcontainer upper in the hierarchy, with better anchors /*System.out.println("global anchors " + anchoredTop + " " + anchoredLeft + " " + anchoredBottom + " " + anchoredRight);*/ boolean [] globalAnchors = {anchoredTop, anchoredLeft, anchoredBottom, anchoredRight}; int globalCount = 0; // number of anchors to be found (at least) for (int i=0; i < 4; i++){ if (globalAnchors[i]){ globalCount++; } } SplitContainer betterSplit = split; boolean [] splitAnchors = new boolean[4]; while (true){ int contacts = findAnchors(split, dockingPanel); splitAnchors[0] = (contacts & AnchorConstraints.ANCHOR_TOP) > 0; splitAnchors[1] = (contacts & AnchorConstraints.ANCHOR_LEFT) > 0; splitAnchors[2] = (contacts & AnchorConstraints.ANCHOR_BOTTOM) > 0; splitAnchors[3] = (contacts & AnchorConstraints.ANCHOR_RIGHT) > 0; int count = 0; for (int i=0; i < 4; i++){ if (globalAnchors[i] && splitAnchors[i]){ count ++; } } if (count >= globalCount){ return split; } else { if (split.getParent() instanceof SplitContainer){ split = (SplitContainer) split.getParent(); } else { return split; // last split container } } } } /** builds an array used to find anchors of a component relative to its ancestor container */ /* private static boolean [] findAnchors(Component comp, Container container){ Rectangle r = SwingUtilities.convertRectangle(comp, new Rectangle(0, 0, comp.getWidth(), comp.getHeight()), container); int x = container.getX(); int y = container.getY(); int w = container.getWidth(); int h = container.getHeight(); boolean [] anchors = new boolean [4]; anchors[0] = Math.abs( y - r.y) < 5; anchors[1] = Math.abs(x - r.x) < 5; anchors[2] = Math.abs(y + h - r.y - r.height) < 30; anchors[3] = Math.abs(x + w - r.x - r.width) < 5; return anchors; } */ /** Horizontally divide split and resize the new split * * @since 2004/04/24 * */ private static void hSplitAndResize(Component base, Component left, Component right, double proportion){ Container parent = base.getParent(); SplitContainer newSplit = new SplitContainer(JSplitPane. HORIZONTAL_SPLIT); DockingUtilities.replaceChild(parent, base, newSplit); newSplit.setLeftComponent( left); newSplit.setRightComponent(right); SwingUtilities.invokeLater(new SplitResizer(newSplit, proportion)); } /** Vertically divide split and resize the new split * * @since 2004/04/24 * */ private static void vSplitAndResize(Component base, Component top, Component bottom, double proportion){ Container parent = base.getParent(); SplitContainer newSplit = new SplitContainer(JSplitPane. VERTICAL_SPLIT); DockingUtilities.replaceChild(parent, base, newSplit); newSplit.setTopComponent( top); newSplit.setBottomComponent(bottom); SwingUtilities.invokeLater(new SplitResizer(newSplit, proportion)); } /** look up the split hierarchy to find which borders a component is touching * * @param base the component to find anchors for * @param ancestorContainer the top level ancestor used to stop searching */ public static int findAnchors(Component base, Container ancestorContainer){ int contact = AnchorConstraints.ANCHOR_TOP|AnchorConstraints.ANCHOR_LEFT |AnchorConstraints.ANCHOR_BOTTOM|AnchorConstraints.ANCHOR_RIGHT; Component comp = base.getParent(); Component child = base; while (comp != null && comp != ancestorContainer && contact != 0){ if (comp instanceof SplitContainer){ SplitContainer sc = (SplitContainer) comp; if (sc.getOrientation() == JSplitPane.VERTICAL_SPLIT){ if (sc.getTopComponent() == child){ contact = contact & (~AnchorConstraints.ANCHOR_BOTTOM); // not at bottom } else { contact = contact & (~AnchorConstraints.ANCHOR_TOP); // not on top } } else { if (sc.getLeftComponent() == child){ contact = contact & (~AnchorConstraints.ANCHOR_RIGHT); // not right } else { contact = contact & (~AnchorConstraints.ANCHOR_LEFT); // not left } } } child = comp; comp = comp.getParent(); } return contact; } /** Tries to find the best position to insert an hidden dockable, and insert it * @deprecated use getInsertionDockingAction / applyDockingAction instead */ public static SingleDockableContainer insertDockable(Container relativeAncestorContainer, Dockable dockable, RelativeDockablePosition position) { if (position == null){ // for safety position = new RelativeDockablePosition(0,0.8,0.5,0.2); } SingleDockableContainer dockableContainer = null; if (relativeAncestorContainer.getComponentCount() == 0){ // empty docking panel dockableContainer = DockableContainerFactory.getFactory(). createDockableContainer(dockable, DockableContainerFactory.PARENT_DESKTOP); // default central insertion relativeAncestorContainer.add((Component)dockableContainer, BorderLayout.CENTER); relativeAncestorContainer.invalidate(); // 2005/05/04 relativeAncestorContainer.validate(); relativeAncestorContainer.repaint(); } else { dockableContainer = DockableContainerFactory.getFactory(). createDockableContainer(dockable, DockableContainerFactory.PARENT_SPLIT_CONTAINER); // convert relative positionning to current positionning (depending // on the current size of dockingPanel) int x = (int) (position.getX() * relativeAncestorContainer.getWidth()); int y = (int) (position.getY() * relativeAncestorContainer.getHeight()); int w = (int) (position.getWidth() * relativeAncestorContainer.getWidth()); int h = (int) (position.getHeight() * relativeAncestorContainer.getHeight()); int centerX = x + w / 2; int centerY = y + h / 2; SplitContainer split = findBestContainer(relativeAncestorContainer, position); if (split != null){ // ok we've found one /*Rectangle splitRect = SwingUtilities.convertRectangle(split, new Rectangle(0, 0, split.getWidth(), split.getHeight()), relativeAncestorContainer);*/ //int contacts = findAnchors(split, relativeAncestorContainer); int contacts = position.getAnchors(); // we use the anchors that // were computed on closing // heuristics : try to find an anchor, and which component(left/right) // is nearer of center /*boolean anchoredTop = Math.abs( y - splitRect.y) < 5; boolean anchoredLeft = Math.abs(x - splitRect.x) < 5; boolean anchoredBottom = Math.abs(y + h - splitRect.y - splitRect.height) < 30; boolean anchoredRight = Math.abs(x + w - splitRect.x - splitRect.width) < 5;*/ boolean anchoredTop = (contacts & AnchorConstraints.ANCHOR_TOP)>0; boolean anchoredLeft =(contacts & AnchorConstraints.ANCHOR_LEFT)>0; boolean anchoredBottom = (contacts & AnchorConstraints.ANCHOR_BOTTOM)>0; boolean anchoredRight = (contacts & AnchorConstraints.ANCHOR_RIGHT)>0; // System.out.println("anchors : " + anchoredTop + ", "+ anchoredLeft + ", " // + anchoredBottom + ", " + anchoredRight); Component left = split.getLeftComponent(); Component right = split.getRightComponent(); Point leftCenter = SwingUtilities.convertPoint(left, left.getWidth() / 2, left.getHeight() / 2, relativeAncestorContainer); Point rightCenter = SwingUtilities.convertPoint(right, right.getWidth() / 2, right.getHeight() / 2, relativeAncestorContainer); int leftDist = (leftCenter.x - x) * (leftCenter.x - x) + (leftCenter.y - y) * (leftCenter.y); int rightDist = (rightCenter.x - x) * (rightCenter.x - x) + (rightCenter.y - y) * (rightCenter.y); Point bestCenter; Component bestComp; if (leftDist < rightDist) { bestCenter = leftCenter; bestComp = left; } else { bestCenter = rightCenter; bestComp = right; } //2006/09/12 /* If the split matches the size of the component, then * we'll have to split it (and not split one of its children) */ float splitWidthRatio = Math.abs(1 - split.getWidth() / (float)w); float splitHeightRatio = Math.abs(1 - split.getHeight() / (float)h); /** this will happen only when anchors are not too strict (like top+right) * for wider anchors (left-top-right) this ration is not used as * superflous */ if (split.getOrientation() == JSplitPane.VERTICAL_SPLIT) { Component top = split.getTopComponent(); Component bottom = split.getBottomComponent(); int topH = top.getHeight(); int bottomH = bottom.getHeight(); // proportions used when splitting a vertical split vertically float proportionTopH = h / (float)topH; float proportionBottomH = h / (float)bottomH; if (proportionTopH >= 0.6f){ // not too big proportionTopH = 0.6f; } if (proportionBottomH >= 0.6f){ // not too big proportionBottomH = 0.6f; } // proportions used when splitting a vertical split horizontally int splitW = split.getWidth(); float proportionW = w / (float) splitW; if (proportionW >= 0.8f){ // not too big proportionW = 0.8f; } if (anchoredTop) { if (anchoredLeft) { if (anchoredBottom) { // TLB = full left SplitContainer newSplit = new SplitContainer(JSplitPane. HORIZONTAL_SPLIT); DockingUtilities.replaceChild(split.getParent(), split, newSplit); newSplit.setLeftComponent( (Component) dockableContainer); newSplit.setRightComponent(split); SwingUtilities.invokeLater(new SplitResizer(newSplit, proportionW)); } else { // Top + left if (splitWidthRatio < 0.1f && split.getHeight() > h){//2006/09/12 // almost the same width, but the split is taller : we split it // vertically SplitContainer newSplit = new SplitContainer(JSplitPane. VERTICAL_SPLIT); DockingUtilities.replaceChild(split.getParent(), split, newSplit); newSplit.setTopComponent( (Component) dockableContainer); newSplit.setBottomComponent(split); SwingUtilities.invokeLater(new SplitResizer(newSplit, h / (float)split.getHeight())); } else { SplitContainer newSplit = new SplitContainer(JSplitPane. HORIZONTAL_SPLIT); DockingUtilities.replaceChild(split, top, newSplit); newSplit.setLeftComponent( (Component) dockableContainer); newSplit.setRightComponent(top); SwingUtilities.invokeLater(new SplitResizer(newSplit, proportionW)); } } } else if (anchoredRight) { // TR if (anchoredBottom) { // TRB = full right SplitContainer newSplit = new SplitContainer(JSplitPane. HORIZONTAL_SPLIT); DockingUtilities.replaceChild(split.getParent(), split, newSplit); newSplit.setRightComponent( (Component) dockableContainer); newSplit.setLeftComponent(split); SwingUtilities.invokeLater(new SplitResizer(newSplit, 1-proportionW)); } else { if (splitWidthRatio < 0.1f && split.getHeight() > h){ // 2006/09/12 // almost the same width, but the split is taller : we split it // vertically SplitContainer newSplit = new SplitContainer(JSplitPane. VERTICAL_SPLIT); DockingUtilities.replaceChild(split.getParent(), split, newSplit); newSplit.setTopComponent( (Component) dockableContainer); newSplit.setBottomComponent(split); SwingUtilities.invokeLater(new SplitResizer(newSplit, h / (float)split.getHeight())); } else { SplitContainer newSplit = new SplitContainer(JSplitPane. HORIZONTAL_SPLIT); DockingUtilities.replaceChild(split, top, newSplit); newSplit.setLeftComponent(top); newSplit.setRightComponent( (Component) dockableContainer); SwingUtilities.invokeLater(new SplitResizer(newSplit, 1-proportionW)); } } } else { // just anchored top SplitContainer newSplit = new SplitContainer(JSplitPane. VERTICAL_SPLIT); DockingUtilities.replaceChild(split, top, newSplit); newSplit.setTopComponent( (Component) dockableContainer); newSplit.setBottomComponent(top); SwingUtilities.invokeLater(new SplitResizer(newSplit, proportionTopH)); } } else if (anchoredBottom) { // but not anchoredTop if (anchoredLeft) { //BL if (anchoredRight) { //BLR = full bottom SplitContainer newSplit = new SplitContainer(JSplitPane. VERTICAL_SPLIT); DockingUtilities.replaceChild(split, bottom, newSplit); newSplit.setTopComponent(bottom); newSplit.setBottomComponent( (Component) dockableContainer); SwingUtilities.invokeLater(new SplitResizer(newSplit, 1-proportionBottomH)); } else { if (splitWidthRatio < 0.1f && split.getHeight() > h){ // 2006/09/12 // almost the same width, but the split is taller : we split it // vertically SplitContainer newSplit = new SplitContainer(JSplitPane. VERTICAL_SPLIT); DockingUtilities.replaceChild(split.getParent(), split, newSplit); newSplit.setBottomComponent( (Component) dockableContainer); newSplit.setTopComponent(split); SwingUtilities.invokeLater(new SplitResizer(newSplit, 1- h / (float)split.getHeight())); } else { SplitContainer newSplit = new SplitContainer(JSplitPane. HORIZONTAL_SPLIT); DockingUtilities.replaceChild(split, bottom, newSplit); newSplit.setLeftComponent( (Component) dockableContainer); newSplit.setRightComponent(bottom); SwingUtilities.invokeLater(new SplitResizer(newSplit, proportionW)); } } } else if (anchoredRight) { // BR if (splitWidthRatio < 0.1f && split.getHeight() > h){ // 2006/09/12 // almost the same width, but the split is taller : we split it // vertically SplitContainer newSplit = new SplitContainer(JSplitPane. VERTICAL_SPLIT); DockingUtilities.replaceChild(split.getParent(), split, newSplit); newSplit.setBottomComponent( (Component) dockableContainer); newSplit.setTopComponent(split); SwingUtilities.invokeLater(new SplitResizer(newSplit, 1 - h / (float)split.getHeight())); } else { SplitContainer newSplit = new SplitContainer(JSplitPane. HORIZONTAL_SPLIT); DockingUtilities.replaceChild(split, bottom, newSplit); newSplit.setLeftComponent(bottom); newSplit.setRightComponent( (Component) dockableContainer); SwingUtilities.invokeLater(new SplitResizer(newSplit, 1-proportionW)); } } else { // just anchored bottom SplitContainer newSplit = new SplitContainer(JSplitPane. VERTICAL_SPLIT); DockingUtilities.replaceChild(split, bottom, newSplit); newSplit.setTopComponent(bottom); newSplit.setBottomComponent( (Component) dockableContainer); SwingUtilities.invokeLater(new SplitResizer(newSplit, 1-proportionBottomH)); } } else if (anchoredLeft) { // not anchored on top / bottom if (anchoredRight){ //2005/10/10 // left + right on a vertical split, means we have to insert a new component // in between int yTop = y; int yBottom = split.getHeight() - y - h; int splitTop = top.getHeight(); int splitBottom = bottom.getHeight(); SplitContainer newSplit = new SplitContainer(JSplitPane. VERTICAL_SPLIT); DockingUtilities.replaceChild(split, bestComp, newSplit); if (bestComp == top){ newSplit.setTopComponent(bestComp); newSplit.setBottomComponent((Component) dockableContainer); SwingUtilities.invokeLater(new SplitResizer(split, (split.getHeight() - yBottom)/(float) split.getHeight())); SwingUtilities.invokeLater(new SplitResizer(newSplit, yTop/(float) split.getHeight())); } else { newSplit.setBottomComponent(bestComp); newSplit.setTopComponent((Component) dockableContainer); SwingUtilities.invokeLater(new SplitResizer(split, yTop/(float) split.getHeight())); SwingUtilities.invokeLater(new SplitResizer(newSplit, h/(float) splitBottom)); } } else {// only left SplitContainer newSplit = new SplitContainer(JSplitPane. HORIZONTAL_SPLIT); DockingUtilities.replaceChild(split, bestComp, newSplit); newSplit.setRightComponent(bestComp); newSplit.setLeftComponent( (Component) dockableContainer); SwingUtilities.invokeLater(new SplitResizer(newSplit, proportionW)); } } else if (anchoredRight) { SplitContainer newSplit = new SplitContainer(JSplitPane. HORIZONTAL_SPLIT); DockingUtilities.replaceChild(split, bestComp, newSplit); newSplit.setLeftComponent(bestComp); newSplit.setRightComponent( (Component) dockableContainer); SwingUtilities.invokeLater(new SplitResizer(newSplit, 1-proportionW)); } else { // not anchored at all, split verticaly and add // todo : check how it's done now for the split-h part and do the same here SplitContainer newSplit = new SplitContainer(JSplitPane. VERTICAL_SPLIT); DockingUtilities.replaceChild(split, bestComp, newSplit); if (bestCenter.y < centerY) { newSplit.setTopComponent(bestComp); newSplit.setBottomComponent( (Component) dockableContainer); SwingUtilities.invokeLater(new SplitResizer(newSplit, 1-proportionBottomH)); } else { newSplit.setBottomComponent(bestComp); newSplit.setTopComponent( (Component) dockableContainer); SwingUtilities.invokeLater(new SplitResizer(newSplit, proportionTopH)); } } } else { // horizontal split // proportions used when splitting a horizontal split horizontally float proportionLeftW = w / (float)left.getWidth(); float proportionRightW = w / (float)right.getWidth(); if (proportionLeftW >= 0.8f){ // not too big proportionLeftW = 0.8f; } if (proportionRightW >= 0.8f){ // not too big proportionRightW = 0.8f; } // proportions used when splitting a horizontal split vertically int splitH = split.getHeight(); float proportionH = h / (float) splitH; if (proportionH >= 0.6f){ // not too big proportionH = 0.6f; } if (anchoredTop) { if (anchoredLeft) { if (anchoredBottom) { // TLB = full left SplitContainer newSplit = new SplitContainer(JSplitPane. HORIZONTAL_SPLIT); DockingUtilities.replaceChild(split, left, newSplit); newSplit.setLeftComponent( (Component) dockableContainer); newSplit.setRightComponent(left); SwingUtilities.invokeLater(new SplitResizer(newSplit, proportionLeftW)); } else if (anchoredRight){ // TLR = full top SplitContainer newSplit = new SplitContainer(JSplitPane. VERTICAL_SPLIT); DockingUtilities.replaceChild(split.getParent(), split, newSplit); newSplit.setTopComponent( (Component) dockableContainer); newSplit.setBottomComponent(split); SwingUtilities.invokeLater(new SplitResizer(newSplit, proportionH)); } else { // just anchored top/left if (splitWidthRatio < 0.1f && split.getHeight() > h){ // 2006/09/12 // almost the same width, but the split is taller : we split it // vertically SplitContainer newSplit = new SplitContainer(JSplitPane. VERTICAL_SPLIT); DockingUtilities.replaceChild(split.getParent(), split, newSplit); newSplit.setTopComponent( (Component) dockableContainer); newSplit.setBottomComponent(split); SwingUtilities.invokeLater(new SplitResizer(newSplit, h / (float)split.getHeight())); } else { // otherwise we just split vertically on the left side SplitContainer newSplit = new SplitContainer(JSplitPane. VERTICAL_SPLIT); DockingUtilities.replaceChild(split, left, newSplit); newSplit.setTopComponent( (Component) dockableContainer); newSplit.setBottomComponent(left); SwingUtilities.invokeLater(new SplitResizer(newSplit, proportionH)); } } } else if (anchoredRight) { // Top but not left if (anchoredBottom) { // top + right + bottom == full right SplitContainer newSplit = new SplitContainer(JSplitPane. HORIZONTAL_SPLIT); DockingUtilities.replaceChild(split, right, newSplit); newSplit.setRightComponent( (Component) dockableContainer); newSplit.setLeftComponent(right); SwingUtilities.invokeLater(new SplitResizer(newSplit, 1-proportionRightW)); } else { // top + right if (splitWidthRatio < 0.1f && split.getHeight() > h){ // 2006/09/12 // almost the same width, but the split is taller : we split it // vertically SplitContainer newSplit = new SplitContainer(JSplitPane. VERTICAL_SPLIT); DockingUtilities.replaceChild(split.getParent(), split, newSplit); newSplit.setTopComponent( (Component) dockableContainer); newSplit.setBottomComponent(split); SwingUtilities.invokeLater(new SplitResizer(newSplit, h / (float)split.getHeight())); } else { SplitContainer newSplit = new SplitContainer(JSplitPane. VERTICAL_SPLIT); DockingUtilities.replaceChild(split, right, newSplit); newSplit.setBottomComponent(right); newSplit.setTopComponent( (Component) dockableContainer); SwingUtilities.invokeLater(new SplitResizer(newSplit, proportionH)); } } } else if (anchoredBottom){ //2005/10/10 // top + bottom : create a horizontal split // as we are inserting a vertical element into a horizontal split // we have to adjust the width on both sides int xLeft = x; int xRight = split.getWidth() - x - w; int splitLeft = left.getWidth(); int splitRight = right.getWidth(); SplitContainer newSplit = new SplitContainer(JSplitPane. HORIZONTAL_SPLIT); DockingUtilities.replaceChild(split, bestComp, newSplit); if (bestComp == left){ newSplit.setLeftComponent(bestComp); newSplit.setRightComponent((Component) dockableContainer); SwingUtilities.invokeLater(new SplitResizer(split, (split.getWidth() - xRight)/(float) split.getWidth())); SwingUtilities.invokeLater(new SplitResizer(newSplit, xLeft/(float) split.getWidth())); } else { newSplit.setRightComponent(bestComp); newSplit.setLeftComponent((Component) dockableContainer); SwingUtilities.invokeLater(new SplitResizer(split, xLeft/(float) split.getWidth())); SwingUtilities.invokeLater(new SplitResizer(newSplit, w/(float) splitRight)); } } else { // just anchored top if (splitWidthRatio < 0.1f && split.getHeight() > h){ // 2006/09/12 // almost the same width, but the split is taller : we split it // vertically SplitContainer newSplit = new SplitContainer(JSplitPane. VERTICAL_SPLIT); DockingUtilities.replaceChild(split.getParent(), split, newSplit); newSplit.setTopComponent( (Component) dockableContainer); newSplit.setBottomComponent(split); SwingUtilities.invokeLater(new SplitResizer(newSplit, h / (float)split.getHeight())); } else { SplitContainer newSplit = new SplitContainer(JSplitPane. VERTICAL_SPLIT); DockingUtilities.replaceChild(split, bestComp, newSplit); newSplit.setTopComponent( (Component) dockableContainer); newSplit.setBottomComponent(bestComp); SwingUtilities.invokeLater(new SplitResizer(newSplit, proportionH)); } } } else if (anchoredBottom) { // but not anchoredTop if (anchoredLeft) { if (anchoredRight) { // BLR == full bottom SplitContainer newSplit = new SplitContainer(JSplitPane. VERTICAL_SPLIT); DockingUtilities.replaceChild(split.getParent(), split, newSplit); newSplit.setTopComponent(split); newSplit.setBottomComponent( (Component) dockableContainer); SwingUtilities.invokeLater(new SplitResizer(newSplit, 1-proportionH)); } else { // bottom + left if (splitWidthRatio < 0.1f && split.getHeight() > h){ // 2006/09/12 // almost the same width, but the split is taller : we split it // vertically SplitContainer newSplit = new SplitContainer(JSplitPane. VERTICAL_SPLIT); DockingUtilities.replaceChild(split.getParent(), split, newSplit); newSplit.setBottomComponent( (Component) dockableContainer); newSplit.setTopComponent(split); SwingUtilities.invokeLater(new SplitResizer(newSplit, 1 - h / (float)split.getHeight())); } else { SplitContainer newSplit = new SplitContainer(JSplitPane. VERTICAL_SPLIT); DockingUtilities.replaceChild(split, left, newSplit); newSplit.setBottomComponent( (Component) dockableContainer); newSplit.setTopComponent(left); SwingUtilities.invokeLater(new SplitResizer(newSplit, 1-proportionH)); } } } else if (anchoredRight) { // bottom + right if (splitWidthRatio < 0.1f && split.getHeight() > h){ // 2006/09/12 // almost the same width, but the split is taller : we split it // vertically SplitContainer newSplit = new SplitContainer(JSplitPane. VERTICAL_SPLIT); DockingUtilities.replaceChild(split.getParent(), split, newSplit); newSplit.setBottomComponent( (Component) dockableContainer); newSplit.setTopComponent(split); SwingUtilities.invokeLater(new SplitResizer(newSplit, 1- h / (float)split.getHeight())); } else { SplitContainer newSplit = new SplitContainer(JSplitPane. VERTICAL_SPLIT); DockingUtilities.replaceChild(split, right, newSplit); newSplit.setTopComponent(right); newSplit.setBottomComponent( (Component) dockableContainer); SwingUtilities.invokeLater(new SplitResizer(newSplit, 1-proportionH)); } } else { // just anchored bottom if (splitWidthRatio < 0.1f && split.getHeight() > h){ // 2006/09/12 // almost the same width, but the split is taller : we split it // vertically SplitContainer newSplit = new SplitContainer(JSplitPane. VERTICAL_SPLIT); DockingUtilities.replaceChild(split.getParent(), split, newSplit); newSplit.setBottomComponent( (Component) dockableContainer); newSplit.setTopComponent(split); SwingUtilities.invokeLater(new SplitResizer(newSplit, 1- h / (float)split.getHeight())); } else { SplitContainer newSplit = new SplitContainer(JSplitPane. VERTICAL_SPLIT); DockingUtilities.replaceChild(split, bestComp, newSplit); newSplit.setTopComponent(bestComp); newSplit.setBottomComponent( (Component) dockableContainer); SwingUtilities.invokeLater(new SplitResizer(newSplit, 1-proportionH)); } } } else if (anchoredLeft) { // not anchored on top / bottom if (anchoredRight){ // left + right... we have to split vertically SplitContainer newSplit = new SplitContainer(JSplitPane. VERTICAL_SPLIT); DockingUtilities.replaceChild(split.getParent(), split, newSplit); newSplit.setTopComponent( (Component) dockableContainer); newSplit.setBottomComponent(split); // todo : check this case : why is the new component on top SwingUtilities.invokeLater(new SplitResizer(newSplit, proportionH)); } else { // just left if (splitWidthRatio < 0.1f && split.getHeight() > h){ // 2006/09/12 // almost the same width, but the split is taller : we split it // vertically SplitContainer newSplit = new SplitContainer(JSplitPane. VERTICAL_SPLIT); DockingUtilities.replaceChild(split.getParent(), split, newSplit); newSplit.setTopComponent( (Component) dockableContainer); newSplit.setBottomComponent(split); SwingUtilities.invokeLater(new SplitResizer(newSplit, h / (float)split.getHeight())); } else { SplitContainer newSplit = new SplitContainer(JSplitPane. HORIZONTAL_SPLIT); DockingUtilities.replaceChild(split, left, newSplit); newSplit.setRightComponent(left); newSplit.setLeftComponent( (Component) dockableContainer); SwingUtilities.invokeLater(new SplitResizer(newSplit, proportionLeftW)); } } } else if (anchoredRight) { if (splitWidthRatio < 0.1f && split.getHeight() > h){ // 2006/09/12 // almost the same width, but the split is taller : we split it // vertically SplitContainer newSplit = new SplitContainer(JSplitPane. VERTICAL_SPLIT); DockingUtilities.replaceChild(split.getParent(), split, newSplit); newSplit.setTopComponent( (Component) dockableContainer); newSplit.setBottomComponent(split); SwingUtilities.invokeLater(new SplitResizer(newSplit, h / (float)split.getHeight())); } else { SplitContainer newSplit = new SplitContainer(JSplitPane. HORIZONTAL_SPLIT); DockingUtilities.replaceChild(split, right, newSplit); newSplit.setLeftComponent(right); newSplit.setRightComponent( (Component) dockableContainer); SwingUtilities.invokeLater(new SplitResizer(newSplit, 1-proportionRightW)); } } else { // not anchored at all // this part can be improved : // - we know we're into an horizontal split // - we can guess if the component was horizontaly splitted or vertically, // and on which side of the split if was (bestComp) float widthIfSplitH = bestComp.getWidth()/2; float heightIfSplitH = bestComp.getHeight(); float widthIfSplitV = bestComp.getWidth(); float heightIfSplitV = bestComp.getHeight()/2; // now which case keeps the best proportions ? float whH = widthIfSplitH / heightIfSplitH; float whV = widthIfSplitV / heightIfSplitV; float whBefore = w / (float)h; if (Math.abs(whBefore - whV) < Math.abs(whBefore - whH)){ // nearer of V SplitContainer newSplit = new SplitContainer(JSplitPane. VERTICAL_SPLIT); DockingUtilities.replaceChild(split, bestComp, newSplit); if (bestCenter.y < centerY) { newSplit.setTopComponent(bestComp); newSplit.setBottomComponent( (Component) dockableContainer); SwingUtilities.invokeLater(new SplitResizer(newSplit, 1-proportionH)); } else { newSplit.setBottomComponent(bestComp); newSplit.setTopComponent( (Component) dockableContainer); SwingUtilities.invokeLater(new SplitResizer(newSplit, proportionH)); } } else { SplitContainer newSplit = new SplitContainer(JSplitPane. HORIZONTAL_SPLIT); DockingUtilities.replaceChild(split, bestComp, newSplit); if (bestCenter.x < centerX) { newSplit.setLeftComponent(bestComp); newSplit.setRightComponent( (Component) dockableContainer); SwingUtilities.invokeLater(new SplitResizer(newSplit, proportionRightW)); } else { newSplit.setRightComponent(bestComp); newSplit.setLeftComponent( (Component) dockableContainer); SwingUtilities.invokeLater(new SplitResizer(newSplit, proportionLeftW)); } } } } } else { // 2004/04/01 (this part was missing) ------------------------------ // one component, but not a split container // heuristics : try to find an anchor boolean anchoredTop = y < 5; boolean anchoredLeft = x < 5; boolean anchoredBottom = Math.abs(y + h - relativeAncestorContainer.getHeight()) < 5; boolean anchoredRight = Math.abs(x + w - relativeAncestorContainer.getWidth()) < 5; Component singleComp = relativeAncestorContainer.getComponent(0); float proportionW = w / (float) relativeAncestorContainer.getWidth(); if (proportionW >= 0.8f){ // not too big proportionW = 0.8f; } float proportionH = h / (float) relativeAncestorContainer.getHeight(); if (proportionH >= 0.6f){ // not too big proportionH = 0.6f; } if (anchoredTop){ if (anchoredLeft){ if (anchoredBottom){ hSplitAndResize(singleComp, (Component) dockableContainer, singleComp, proportionW); } else if (anchoredRight){ // top + left + right == TOP vSplitAndResize(singleComp, (Component) dockableContainer, singleComp, proportionH); } else { // top + left... what should we do ? if (w > h){ vSplitAndResize(singleComp, (Component) dockableContainer, singleComp, proportionH); } else { hSplitAndResize(singleComp, (Component) dockableContainer, singleComp, proportionW); } } } else if (anchoredRight){ // top + right (not left) if (anchoredBottom){ // top + right + bottom == on the right hSplitAndResize(singleComp, singleComp, (Component) dockableContainer, 1-proportionW); } else { // top + right if (w > h){ // on top vSplitAndResize(singleComp, (Component) dockableContainer, singleComp, proportionH); } else { // on the right hSplitAndResize(singleComp, singleComp, (Component) dockableContainer, 1-proportionW); } } } else { // top only vSplitAndResize(singleComp, (Component) dockableContainer, singleComp, proportionH); } } else if (anchoredLeft){ //left (but not top) if (anchoredBottom){ // left + bot if (anchoredRight){ // == bottom vSplitAndResize(singleComp, singleComp, (Component) dockableContainer, 1-proportionH); } else { // left + bottom if (w > h){ // bottom vSplitAndResize(singleComp, singleComp, (Component) dockableContainer, 1-proportionH); } else { // on the left hSplitAndResize(singleComp, (Component) dockableContainer, singleComp, proportionW); } } } else if (anchoredRight){ // left + right, but not top/bottom... if (centerY < relativeAncestorContainer.getHeight()/2){ // center is upper part vSplitAndResize(singleComp, (Component) dockableContainer, singleComp, proportionH); } else { // lower part vSplitAndResize(singleComp, singleComp, (Component) dockableContainer, 1-proportionH); } } else { // left only hSplitAndResize(singleComp, (Component) dockableContainer, singleComp, proportionW); } } else if (anchoredBottom){ // bottom, but not top/left if (anchoredRight){ if (w > h){ // bottom vSplitAndResize(singleComp, singleComp, (Component) dockableContainer, 1-proportionH); } else { // on the right hSplitAndResize(singleComp, singleComp, (Component) dockableContainer, 1-proportionW); } } else { // just bottom vSplitAndResize(singleComp, singleComp, (Component) dockableContainer, 1-proportionH); } } else if (anchoredRight){ // just right hSplitAndResize(singleComp, singleComp, (Component) dockableContainer, 1-proportionW); } else { // no anchors if (centerY < relativeAncestorContainer.getHeight()/2){ // center is upper part vSplitAndResize(singleComp, (Component) dockableContainer, singleComp, proportionH); } else { vSplitAndResize(singleComp, singleComp, (Component) dockableContainer, 1-proportionH); } } } // 2004/04/01 (end of missing part) ------------------------------ } return dockableContainer; //DockingActionEvent action = getInsertionDockingAction(relativeAncestorContainer, dockable, position); //return applyDockingAction(dockable, action); } /** returns a docking action event corresponding to the insertion point and method * of the dockable. */ public static DockingActionEvent getInsertionDockingAction(Container relativeAncestorContainer, Dockable dockable, DockableState dockableState, DockableState newState){ RelativeDockablePosition position = dockableState.getPosition(); DockingDesktop desktop = dockableState.getDesktop(); int initialState = dockableState.getState(); int nextState = newState.getState(); if (position == null){ // for safety position = new RelativeDockablePosition(0,0.8,0.5,0.2); } SingleDockableContainer dockableContainer = null; if (relativeAncestorContainer.getComponentCount() == 0){ // empty docking panel return new DockingActionAddDockableEvent(desktop, dockable, initialState, nextState, relativeAncestorContainer); } else { // convert relative positionning to current positionning (depending // on the current size of dockingPanel) int x = (int) (position.getX() * relativeAncestorContainer.getWidth()); int y = (int) (position.getY() * relativeAncestorContainer.getHeight()); int w = (int) (position.getWidth() * relativeAncestorContainer.getWidth()); int h = (int) (position.getHeight() * relativeAncestorContainer.getHeight()); int centerX = x + w / 2; int centerY = y + h / 2; SplitContainer split = findBestContainer(relativeAncestorContainer, position); if (split != null){ // ok we've found one Rectangle splitRect = SwingUtilities.convertRectangle(split, new Rectangle(0, 0, split.getWidth(), split.getHeight()), relativeAncestorContainer); // heuristics : try to find an anchor, and which component(left/right) // is nearer of center boolean anchoredTop = Math.abs( y - splitRect.y) < 5; boolean anchoredLeft = Math.abs(x - splitRect.x) < 5; boolean anchoredBottom = Math.abs(y + h - splitRect.y - splitRect.height) < 30/*5*/; boolean anchoredRight = Math.abs(x + w - splitRect.x - splitRect.width) < 5; Component left = split.getLeftComponent(); Component right = split.getRightComponent(); Point leftCenter = SwingUtilities.convertPoint(left, left.getWidth() / 2, left.getHeight() / 2, relativeAncestorContainer); Point rightCenter = SwingUtilities.convertPoint(right, right.getWidth() / 2, right.getHeight() / 2, relativeAncestorContainer); int leftDist = (leftCenter.x - x) * (leftCenter.x - x) + (leftCenter.y - y) * (leftCenter.y); int rightDist = (rightCenter.x - x) * (rightCenter.x - x) + (rightCenter.y - y) * (rightCenter.y); Point bestCenter; Component bestComp; if (leftDist < rightDist) { bestCenter = leftCenter; bestComp = left; } else { bestCenter = rightCenter; bestComp = right; } if (split.getOrientation() == JSplitPane.VERTICAL_SPLIT) { Component top = split.getTopComponent(); Component bottom = split.getBottomComponent(); int topH = top.getHeight(); int bottomH = bottom.getHeight(); // proportions used when splitting a vertical split vertically float proportionTopH = h / (float)topH; float proportionBottomH = h / (float)bottomH; if (proportionTopH >= 0.6f){ // not too big proportionTopH = 0.6f; } if (proportionBottomH >= 0.6f){ // not too big proportionBottomH = 0.6f; } // proportions used when splitting a vertical split horizontally int splitW = split.getWidth(); float proportionW = w / (float) splitW; if (proportionW >= 0.8f){ // not too big proportionW = 0.8f; } if (anchoredTop) { if (anchoredLeft) { if (anchoredBottom) { return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, split, DockingConstants.SPLIT_LEFT, proportionW); } else { return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, top, DockingConstants.SPLIT_LEFT, proportionW); } } else if (anchoredRight) { if (anchoredBottom) { return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, split, DockingConstants.SPLIT_RIGHT, 1-proportionW); } else { return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, top, DockingConstants.SPLIT_RIGHT, 1-proportionW); } } else { // just anchored top return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, top, DockingConstants.SPLIT_TOP, proportionTopH); } } else if (anchoredBottom) { // but not anchoredTop if (anchoredLeft) { if (anchoredRight) { return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, bottom, DockingConstants.SPLIT_BOTTOM, 1-proportionBottomH); } else { return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, bottom, DockingConstants.SPLIT_LEFT, proportionW); } } else if (anchoredRight) { return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, bottom, DockingConstants.SPLIT_RIGHT, 1-proportionW); } else { // just anchored bottom return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, bottom, DockingConstants.SPLIT_BOTTOM, 1-proportionBottomH); } } else if (anchoredLeft) { // not anchored on top / bottom if (anchoredRight){ //2005/10/10 // left + right on a vertical split, means we have to insert a new component // in between int yTop = y; int yBottom = split.getHeight() - y - h; int splitTop = top.getHeight(); int splitBottom = bottom.getHeight(); /*SplitContainer newSplit = new SplitContainer(JSplitPane. VERTICAL_SPLIT); DockingUtilities.replaceChild(split, bestComp, newSplit);*/ if (bestComp == top){ float hParent =( split.getHeight() - yBottom)/(float) split.getHeight() ; float hChild = yTop/(float) split.getHeight(); return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, bestComp, DockingConstants.SPLIT_BOTTOM, hChild, hParent); } else { float hChild = h/(float) splitBottom; float hParent = yTop/(float) split.getHeight(); return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, bestComp, DockingConstants.SPLIT_TOP, hChild, hParent); } } else {// only left return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, bestComp, DockingConstants.SPLIT_LEFT, proportionW); } } else if (anchoredRight) { return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, bestComp, DockingConstants.SPLIT_RIGHT, 1-proportionW); } else { // not anchored at all, split verticaly and add SplitContainer newSplit = new SplitContainer(JSplitPane. VERTICAL_SPLIT); DockingUtilities.replaceChild(split, bestComp, newSplit); if (bestCenter.y < centerY) { return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, bestComp, DockingConstants.SPLIT_BOTTOM, 1-proportionBottomH); } else { return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, bestComp, DockingConstants.SPLIT_TOP, proportionTopH); } } } else { // horizontal split // proportions used when splitting a horizontal split horizontally float proportionLeftW = w / (float)left.getWidth(); float proportionRightW = w / (float)right.getWidth(); if (proportionLeftW >= 0.8f){ // not too big proportionLeftW = 0.8f; } if (proportionRightW >= 0.8f){ // not too big proportionRightW = 0.8f; } // proportions used when splitting a horizontal split vertically int splitH = split.getHeight(); float proportionH = h / (float) splitH; if (proportionH >= 0.6f){ // not too big proportionH = 0.6f; } if (anchoredTop) { if (anchoredLeft) { if (anchoredBottom) { return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, left, DockingConstants.SPLIT_LEFT, proportionLeftW); } else if (anchoredRight){ return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, split, DockingConstants.SPLIT_TOP, proportionH); } else { // just anchored top/left return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, left, DockingConstants.SPLIT_TOP, proportionH); } } else if (anchoredRight) { if (anchoredBottom) { // top + right + bottom return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, right, DockingConstants.SPLIT_RIGHT, 1-proportionRightW); } else { // top + right return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, right, DockingConstants.SPLIT_TOP, proportionH); } } else if (anchoredBottom){ //2005/10/10 // top + bottom : create a horizontal split // as we are inserting a vertical element into a horizontal split // we have to adjust the width on both sides int xLeft = x; int xRight = split.getWidth() - x - w; int splitLeft = left.getWidth(); int splitRight = right.getWidth(); /*SplitContainer newSplit = new SplitContainer(JSplitPane. HORIZONTAL_SPLIT); DockingUtilities.replaceChild(split, bestComp, newSplit);*/ if (bestComp == left){ float parentW = (split.getWidth() - xRight)/(float) split.getWidth(); float childW = xLeft/(float) split.getWidth(); return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, bestComp, DockingConstants.SPLIT_RIGHT, childW, parentW); } else { float parentW = xLeft/(float) split.getWidth(); float childW = w/(float) splitRight; return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, bestComp, DockingConstants.SPLIT_LEFT, childW, parentW); } } else { // just anchored top return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, bestComp, DockingConstants.SPLIT_TOP, proportionH); } } else if (anchoredBottom) { // but not anchoredTop if (anchoredLeft) { if (anchoredRight) { return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, split, DockingConstants.SPLIT_BOTTOM, 1-proportionH); } else { // bottom + left return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, left, DockingConstants.SPLIT_BOTTOM, 1-proportionH); } } else if (anchoredRight) { // bottom + right return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, right, DockingConstants.SPLIT_BOTTOM, 1-proportionH); } else { return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, bestComp, DockingConstants.SPLIT_BOTTOM, 1-proportionH); } } else if (anchoredLeft) { // not anchored on top / bottom return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, left, DockingConstants.SPLIT_LEFT, proportionLeftW); } else if (anchoredRight) { return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, right, DockingConstants.SPLIT_RIGHT, 1-proportionRightW); } else { // not anchored at all, split verticaly and add /*SplitContainer newSplit = new SplitContainer(JSplitPane. VERTICAL_SPLIT); DockingUtilities.replaceChild(split, bestComp, newSplit);*/ if (bestCenter.y < centerY) { return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, bestComp, DockingConstants.SPLIT_BOTTOM, 1-proportionH); } else { return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, bestComp, DockingConstants.SPLIT_TOP, proportionH); } } } } else { // 2004/04/01 (this part was missing) ------------------------------ // one component, but not a split container // heuristics : try to find an anchor boolean anchoredTop = y < 5; boolean anchoredLeft = x < 5; boolean anchoredBottom = Math.abs(y + h - relativeAncestorContainer.getHeight()) < 5; boolean anchoredRight = Math.abs(x + w - relativeAncestorContainer.getWidth()) < 5; Component singleComp = relativeAncestorContainer.getComponent(0); float proportionW = w / (float) relativeAncestorContainer.getWidth(); if (proportionW >= 0.8f){ // not too big proportionW = 0.8f; } float proportionH = h / (float) relativeAncestorContainer.getHeight(); if (proportionH >= 0.6f){ // not too big proportionH = 0.6f; } if (anchoredTop){ if (anchoredLeft){ if (anchoredBottom){ return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, singleComp, DockingConstants.SPLIT_LEFT, proportionW); } else if (anchoredRight){ // top + left + right == TOP return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, singleComp, DockingConstants.SPLIT_TOP, proportionH); } else { // top + left... what should we do ? if (w > h){ // vsplit return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, singleComp, DockingConstants.SPLIT_TOP, proportionH); } else { // hsplit return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, singleComp, DockingConstants.SPLIT_LEFT, proportionW); } } } else if (anchoredRight){ // top + right (not left) if (anchoredBottom){ // top + right + bottom == on the right return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, singleComp, DockingConstants.SPLIT_RIGHT, 1-proportionW); } else { // top + right if (w > h){ // on top return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, singleComp, DockingConstants.SPLIT_TOP, proportionH); } else { // on the right return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, singleComp, DockingConstants.SPLIT_RIGHT, 1-proportionW); } } } else { // top only return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, singleComp, DockingConstants.SPLIT_TOP, proportionH); } } else if (anchoredLeft){ //left (but not top) if (anchoredBottom){ // left + bot if (anchoredRight){ // == bottom return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, singleComp, DockingConstants.SPLIT_BOTTOM, 1-proportionH); } else { // left + bottom if (w > h){ // bottom return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, singleComp, DockingConstants.SPLIT_BOTTOM, 1-proportionH); } else { // on the left return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, singleComp, DockingConstants.SPLIT_LEFT, proportionW); } } } else if (anchoredRight){ // left + right, but not top/bottom... if (centerY < relativeAncestorContainer.getHeight()/2){ // center is upper part return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, singleComp, DockingConstants.SPLIT_TOP, proportionH); } else { // lower part return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, singleComp, DockingConstants.SPLIT_BOTTOM, 1-proportionH); } } else { // left only return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, singleComp, DockingConstants.SPLIT_LEFT, proportionW); } } else if (anchoredBottom){ // bottom, but not top/left if (anchoredRight){ if (w > h){ // bottom return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, singleComp, DockingConstants.SPLIT_BOTTOM, 1-proportionH); } else { // on the right return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, singleComp, DockingConstants.SPLIT_RIGHT, 1-proportionW); } } else { // just bottom return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, singleComp, DockingConstants.SPLIT_BOTTOM, 1-proportionH); } } else if (anchoredRight){ // just right return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, singleComp, DockingConstants.SPLIT_RIGHT, 1-proportionW); } else { // no anchors if (centerY < relativeAncestorContainer.getHeight()/2){ // center is upper part return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, singleComp, DockingConstants.SPLIT_TOP, proportionH); } else { return new DockingActionSplitComponentEvent(desktop, dockable, initialState, nextState, singleComp, DockingConstants.SPLIT_BOTTOM, 1-proportionH); } } } } } public static SingleDockableContainer applyDockingAction(Dockable dockable, DockingActionEvent action){ SingleDockableContainer dockableContainer; switch (action.getActionType()){ case DockingActionEvent.ACTION_ADD_DOCKABLE: DockingActionAddDockableEvent addAction = (DockingActionAddDockableEvent) action; dockableContainer = DockableContainerFactory.getFactory(). createDockableContainer(dockable, DockableContainerFactory.PARENT_DESKTOP); Container relativeAncestorContainer = addAction.getParentContainer(); // default central insertion relativeAncestorContainer.add((Component)dockableContainer, BorderLayout.CENTER); relativeAncestorContainer.invalidate(); // 2005/05/04 relativeAncestorContainer.validate(); relativeAncestorContainer.repaint(); return dockableContainer; case DockingActionEvent.ACTION_SPLIT_COMPONENT: dockableContainer = DockableContainerFactory.getFactory(). createDockableContainer(dockable, DockableContainerFactory.PARENT_SPLIT_CONTAINER); DockingActionSplitComponentEvent splitAction = (DockingActionSplitComponentEvent) action; Component base = splitAction.getBase(); float div = splitAction.getDividorLocation(); DockingConstants.Split splitPosition = splitAction.getSplitPosition(); float parentDiv = splitAction.getParentDividorLocation(); switch (splitPosition.value()){ case DockingConstants.INT_SPLIT_TOP: vSplitAndResize(base, (Container) dockableContainer, base, div); break; case DockingConstants.INT_SPLIT_LEFT: hSplitAndResize(base, (Container) dockableContainer, base, div); break; case DockingConstants.INT_SPLIT_BOTTOM: vSplitAndResize(base, base, (Container) dockableContainer, div); break; case DockingConstants.INT_SPLIT_RIGHT: hSplitAndResize(base, base, (Container) dockableContainer, div); break; } if (parentDiv != -1 && base.getParent() instanceof SplitContainer){ SplitContainer parent = (SplitContainer) base.getParent(); new SplitResizer(parent, parentDiv); } return dockableContainer; default: throw new IllegalArgumentException("Action type not managed : "+ action.getActionType()); } } }vldocking_2.1.4/src/com/vlsolutions/swing/docking/ShadowBorder.java0000644000175000017500000001573310573516350025475 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking; import javax.swing.border.*; import java.awt.Component; import java.awt.Graphics; import java.awt.Insets; import java.awt.*; import javax.swing.*; /** A border using a shadow on right-bottom sides. * *

* Two types of border can be drawn : full shadow border and half shadow border. *

    *
  • full shadow border paints darker lines on top and left to define a rectangular shape * (this is the kind of border used by DockableContainers (DockViews). * half shadow border paints only a shadow (nothing on top and right) : it is used for * DockedTabbedPane contents. *
* * @author Lilian Chamontin, vlsolutions. * @version 1.0 */ public class ShadowBorder implements Border { private static Insets INSETS_FULL = new Insets(3, 2, 5, 5); private static Insets INSETS_HALF = new Insets(1, 1, 5, 5); private static Image shadowImage = new ImageIcon(ShadowBorder.class.getResource("shadow.png")).getImage(); static int shadowW = shadowImage.getWidth(null); static int shadowH = shadowImage.getHeight(null); private Color highlight = UIManager.getColor("controlLtHighlight"); private Color shadow = UIManager.getColor("controlShadow"); private boolean paintTopLeft = true; private Insets insets; /* Constructs a full shadow border */ public ShadowBorder() { this(true); } /** Constructs a full shadow border (if paintTopLeft is true) or a half shadow border * (is false). * */ public ShadowBorder(boolean paintTopLeft) { this.paintTopLeft = paintTopLeft; insets = paintTopLeft? INSETS_FULL : INSETS_HALF; } public boolean isBorderOpaque() { return false; } public void paintBorder(Component component, Graphics graphics, int x, int y, int w, int h) { // top corner graphics.drawImage(shadowImage, x+ w -5, y, x+w, y+5, shadowW-5,0, shadowW, 5, null); // vertical graphics.drawImage(shadowImage, x+ w -5, y+5, x+w, y+h-5, shadowW-5,5, shadowW, shadowH-5, null); // bottom-right corner graphics.drawImage(shadowImage, x+ w -5, y+h-5, x+w, y+h, shadowW-5,shadowH-5, shadowW, shadowH, null); // horizontal graphics.drawImage(shadowImage, x+5, y+h-5, x+w-5, y+h, 5,shadowH-5, shadowW-5, shadowH, null); // bottom left corner graphics.drawImage(shadowImage, x, y+h-5, x+5, y+h, 0, shadowH-5, 5, shadowH, null); if (paintTopLeft){ graphics.setColor(highlight); graphics.drawRect(x + 1, y + 2, w - 7, 1); // graphics.drawRect(x + 1, y + 2, 1, h - 7); graphics.drawLine(x + 1, y + 2, x+1, y + h - 5); graphics.setColor(shadow); graphics.drawRect(x, y + 1, w - 5, h - 6); } } public Insets getBorderInsets(Component component) { return insets; } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/SingleDockableContainer.java0000644000175000017500000001155710573516350027623 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking; /** A SingleDockableContainer is a DockableContainer that can display * a single Dockable component. *

* The components is usually displayed with decorations * (a title bar, docking state management buttons, a drop shadow, ...). *

* This interface is meant for API Extenders in order to provide new kinds of * SingleDockableContainers (if the default implementation, DockView hasn't * got enough features or to provide a different look and feel). * * @author Lilian Chamontin, vlsolutions. * @version 1.0 */ public interface SingleDockableContainer extends DockableContainer { /** Returns the dockable this container is displaying */ public Dockable getDockable(); } vldocking_2.1.4/src/com/vlsolutions/swing/docking/SplitContainer.java0000644000175000017500000004335310573516350026047 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.awt.event.ComponentEvent; import java.awt.geom.*; import com.vlsolutions.swing.docking.event.*; /** A Specialized JSplitPane which accepts drag and drop of DockableContainer. *

* The split container should be used only by the DockingDesktop. *

* It is a SplitPane with bug workarounds and a custom UI (in fact : no UI painting at all, * by default). * * * @author Lilian Chamontin, vlsolutions. * @version 1.0 */ public class SplitContainer extends JSplitPane implements DockDropReceiver { // this is for debugging purpose and will be removed. private static Color [] colors = {Color.RED, Color.BLUE, Color.CYAN, Color.GREEN, Color.MAGENTA, Color.ORANGE, Color.PINK, Color.WHITE, Color.YELLOW}; private static int colorindex = -1; private static final boolean DEBUG = false; private static final String uiClassID = "DockingSplitPaneUI"; /** Constructs a vertically splitted SplitContainer */ public SplitContainer() { this(VERTICAL_SPLIT); } /** Constructs a SplitContainer with the given JSplitPane orientation. */ public SplitContainer(int orientation) { super(orientation); setBorder(null); if (DEBUG){ Color c = colors[ (++colorindex % colors.length)]; setBorder(BorderFactory.createLineBorder(c, 2)); } } /** Overriden for custom UI delegation */ public String getUIClassID() { return uiClassID; } /** Returns a readable String representing this SplitContainer */ public String toString() { if (getOrientation() == HORIZONTAL_SPLIT){ return "SplitContainer[HORIZONTAL, " + getTopComponent() + " / " + getBottomComponent() + ']'; } else { return "SplitContainer[VERTICAL, " + getTopComponent() + " / " + getBottomComponent() + ']'; } } /** Returns a suitable name for when this container is the main child of a Tab (TabbedDockableContainer) */ public String getTabName(){ Component left = getLeftComponent(); if (left instanceof SingleDockableContainer){ return ((SingleDockableContainer)left).getDockable().getDockKey().getTabName(); } else if (left instanceof SplitContainer){ return ((SplitContainer)left).getTabName(); } else { return null; } } /** {@inheritDoc} */ public void processDockableDrag(DockDragEvent event) { scanContainer(event, false); } /** {@inheritDoc} */ public void processDockableDrop(DockDropEvent event) { scanContainer(event, true); } private void scanContainer(DockEvent event, boolean drop) { // reject operation if the source is an ancestor of this view. if (event.getDragSource().getDockableContainer().isAncestorOf(this)){ // this is possible for compound containers (as they contain sub-dockables) // in that case, you cannnot drop a compound into one of its children // 2007/01/08 if (drop){ ((DockDropEvent) event).rejectDrop(); } else { ((DockDragEvent) event).delegateDrag(); } return; } /* Dock is available : * - on borders of the two components * - on the center of the 2 components (meaning : tab'em) */ Point p = event.getMouseEvent().getPoint(); Rectangle compBounds = getLeftComponent().getBounds(); if (compBounds.contains(p)){ scanComponent(getLeftComponent(), event, drop, p, compBounds); }else { getRightComponent().getBounds(compBounds); if (compBounds.contains(p)){ scanComponent(getRightComponent(), event, drop, p, compBounds); } else { // we are elsewhere : reject if (drop) { ( (DockDropEvent) event).rejectDrop(); } else { ( (DockDragEvent) event).rejectDrag(); } } } } // workaround bug #4276222 private boolean isPainted; private boolean hasProportionalLocation; private double proportionalLocation; /** Overriden for a bug workaround*/ public void setDividerLocation(double proportionalLocation){ if (! isPainted){ hasProportionalLocation = true; this.proportionalLocation = proportionalLocation; } else { if (proportionalLocation < 0 ){ // safety checks to avoid exceptions proportionalLocation = 0; } else if (proportionalLocation > 1){ proportionalLocation = 1; } else { super.setDividerLocation(proportionalLocation); } } } public void setDividerLocation(int location) { super.setDividerLocation(location); if (!DockingPreferences.isLightWeightUsageEnabled()){ // ugly repaint trick due to incorrect repaint on linux/mac systems final Window w = SwingUtilities.getWindowAncestor(this); if (w != null){ SwingUtilities.invokeLater(new Runnable(){ public void run(){ w.repaint(); } }); } } } /** overriden for a bug workaround reason */ public void paint(Graphics g){ if (! isPainted){ isPainted = true; if (hasProportionalLocation){ setDividerLocation(proportionalLocation); doLayout(); } } super.paint(g); } /** Resest recursively the left and right components to their preferred size * if possible. (same contract as JSplitPane's). *

* If contained components are SplitContainers, their are also reset to their * preferredSize. * */ public void resetToPreferredSizes(){ super.resetToPreferredSizes(); if (getLeftComponent() instanceof SplitContainer){ ((SplitContainer)getLeftComponent()).resetToPreferredSizes(); } if (getRightComponent() instanceof SplitContainer){ ((SplitContainer)getRightComponent()).resetToPreferredSizes(); } } /** Replaces the child component by a sub-split pane. * @param child one or the two components of this split pane * @param newComp the new component to add * @param position where to put comp / child (i.e if SPLIT_TOP, * a vertical splitpane will be created and comp will be on top of it * (and child at bottom). */ public void split(Component newComp, Component child, DockingConstants.Split position){ SplitContainer split; if (position == DockingConstants.SPLIT_TOP || position == DockingConstants.SPLIT_BOTTOM){ split = new SplitContainer(JSplitPane.VERTICAL_SPLIT); } else /*if (position == DockingConstants.SPLIT_LEFT || position == DockingConstants.SPLIT_RIGHT)*/ { split = new SplitContainer(JSplitPane.HORIZONTAL_SPLIT); } if (getLeftComponent() == child){ remove(child); setLeftComponent(split); if (position == DockingConstants.SPLIT_TOP || position == DockingConstants.SPLIT_LEFT){ split.setLeftComponent(newComp); // for splitpane, left == top split.setRightComponent(child); } else { split.setLeftComponent(child); // for splitpane, left == top split.setRightComponent(newComp); } } else { remove(child); setRightComponent(split); if (position == DockingConstants.SPLIT_TOP || position == DockingConstants.SPLIT_LEFT){ split.setLeftComponent(newComp); // for splitpane, left == top split.setRightComponent(child); } else { split.setLeftComponent(child); // for splitpane, left == top split.setRightComponent(newComp); } } } private void scanComponent(Component comp, DockEvent event, boolean drop, Point p, Rectangle compBounds) { int distTop = p.y - compBounds.y; int distLeft = p.x - compBounds.x; int min = Math.min(distTop, distLeft); int distRight = compBounds.x + compBounds.width - p.x; int distBottom = compBounds.y + compBounds.height - p.y; int min2 = Math.min(distBottom, distRight); min = Math.min(min, min2); Dockable dockable = event.getDragSource().getDockable(); int splitState = DockingUtilities.getDockableStateFromHierarchy(this); int dockableState = dockable.getDockKey().getDockableState(); if (min == distTop) { // dock on top if (drop) { event.setDockingAction(new DockingActionSplitComponentEvent(event.getDesktop(), dockable, dockableState, splitState, comp, DockingConstants.SPLIT_TOP, 0.5f)); ( (DockDropEvent) event).acceptDrop(); event.getDesktop().splitComponent(comp, event.getDragSource().getDockable(), DockingConstants.SPLIT_TOP); } else { Rectangle2D r2d = new Rectangle2D.Float(compBounds.x, compBounds.y, compBounds.width, 20); event.setDockingAction(new DockingActionSplitComponentEvent(event.getDesktop(), dockable, dockableState, splitState, comp, DockingConstants.SPLIT_TOP, 0.5f)); ( (DockDragEvent) event).acceptDrag(r2d); } } else if (min == distLeft) { if (drop) { event.setDockingAction(new DockingActionSplitComponentEvent(event.getDesktop(), dockable, dockableState, splitState, comp, DockingConstants.SPLIT_LEFT, 0.5f)); ( (DockDropEvent) event).acceptDrop(); event.getDesktop().splitComponent(comp, event.getDragSource().getDockable(), DockingConstants.SPLIT_LEFT); } else { Rectangle2D r2d = new Rectangle2D.Float(compBounds.x, compBounds.y, 20, compBounds.height); event.setDockingAction(new DockingActionSplitComponentEvent(event.getDesktop(), dockable, dockableState, splitState, comp, DockingConstants.SPLIT_LEFT, 0.5f)); event.setDockingAction(new DockingActionSplitComponentEvent(event.getDesktop(), dockable, dockable.getDockKey().getDockableState(), splitState, comp, DockingConstants.SPLIT_TOP, 0.5f)); ( (DockDragEvent) event).acceptDrag(r2d); } } else if (min == distBottom) { if (drop) { event.setDockingAction(new DockingActionSplitComponentEvent(event.getDesktop(), dockable, dockableState, splitState, comp, DockingConstants.SPLIT_BOTTOM, 0.5f)); ( (DockDropEvent) event).acceptDrop(); event.getDesktop().splitComponent(comp, event.getDragSource().getDockable(), DockingConstants.SPLIT_BOTTOM); } else { Rectangle2D r2d = new Rectangle2D.Float(compBounds.x, compBounds.y + compBounds.height - 20, compBounds.width, 20); event.setDockingAction(new DockingActionSplitComponentEvent(event.getDesktop(), dockable, dockableState, splitState, comp, DockingConstants.SPLIT_BOTTOM, 0.5f)); ( (DockDragEvent) event).acceptDrag(r2d); } } else { // right if (drop) { event.setDockingAction(new DockingActionSplitComponentEvent(event.getDesktop(), dockable, dockableState, splitState, comp, DockingConstants.SPLIT_RIGHT, 0.5f)); ( (DockDropEvent) event).acceptDrop(); event.getDesktop().splitComponent(comp, event.getDragSource().getDockable(), DockingConstants.SPLIT_RIGHT); } else { Rectangle2D r2d = new Rectangle2D.Float( compBounds.x + compBounds.width - 20, compBounds.y, 20, compBounds.height); event.setDockingAction(new DockingActionSplitComponentEvent(event.getDesktop(), dockable, dockableState, splitState, comp, DockingConstants.SPLIT_RIGHT, 0.5f)); ( (DockDragEvent) event).acceptDrag(r2d); } } } } /* Utility class, resizes a splitcontainer after its size is known (needs an invokelater after * having added it). * allows us to avoid the nasty resizing of a splitpane when a component * is added on the right/bottom (it will then take most of the split surface, * which is not good when we add a small dockable to the right of a big dockable */ class SplitResizer implements Runnable { SplitContainer split; int location; double doubleloc; boolean isDouble; SplitResizer(SplitContainer split, int location) { this.split = split; this.location = location; isDouble = false; } SplitResizer(SplitContainer split, double location) { this.split = split; this.doubleloc = location; isDouble = true; } public void run() { // used as invokeLater, as the size of the splitpane is not known // when split is first inserted. if (isDouble){ split.setDividerLocation(doubleloc); } else { // clamp resizing to the half width/height of the splitpane int maxWidth = split.getWidth() / 2; int maxHeight = split.getHeight() / 2; if (location < 0) { //meaning it's a resize of the opposite component if (split.getOrientation() == JSplitPane.HORIZONTAL_SPLIT) { location = Math.max(maxWidth, split.getWidth() + location); } else { location = Math.max(maxHeight, split.getHeight() + location); } } else { if (split.getOrientation() == JSplitPane.HORIZONTAL_SPLIT) { location = Math.min(maxWidth, location); } else { location = Math.min(maxHeight, location); } } split.setDividerLocation(location); } } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/TabFactory.java0000644000175000017500000000215010573516344025140 0ustar twernertwernerpackage com.vlsolutions.swing.docking; /** A factory that replaces DockViews (with title headers) by tabbed panes with a single tab. *

* This factory provides a unified GUI for single AND tabbed components (with the exception of * auto-hide and single-floating that still use the standard title bars). *

* It is still in an early stage and will be improved in future releases, depending on its * adoption. * * @author Lilian Chamontin, VLSolutions * @since 2.1.3 * */ public class TabFactory extends DefaultDockableContainerFactory { public SingleDockableContainer createDockableContainer(Dockable dockable, int parentType) { switch (parentType){ case PARENT_TABBED_CONTAINER: return new TabbedDockView(dockable); case PARENT_DESKTOP: return new MaximizedDockViewAsTab(dockable);//MaximizedDockView(dockable); case PARENT_SPLIT_CONTAINER: return new DockViewAsTab(dockable); case PARENT_DETACHED_WINDOW: return new DetachedDockView(dockable); default : throw new RuntimeException("Wrong dockable container type"); } } }vldocking_2.1.4/src/com/vlsolutions/swing/docking/TabbedContainerActions.java0000644000175000017500000002540510573516350027454 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking; import java.awt.event.ActionEvent; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.KeyStroke; import javax.swing.UIManager; /** An utility class providing default implementation of usefull actions for pop-up * menus in tab container selectors. *

* * @author Lilian Chamontin, VLSolutions * *@update 2005/10/07 Lilian Chamontin : added the attach action for floating tabs */ public class TabbedContainerActions { // label resources taken from BasicInternalFrameUI... private static final String CLOSE_TEXT = UIManager.getString("DockTabbedPane.closeButtonText"); private static final String ICONIFY_TEXT = UIManager.getString("DockTabbedPane.minimizeButtonText"); private static final String RESTORE_TEXT = UIManager.getString("DockTabbedPane.restoreButtonText"); private static final String MAXIMIZE_TEXT = UIManager.getString("DockTabbedPane.maximizeButtonText"); private static final String FLOAT_TEXT = UIManager.getString("DockTabbedPane.floatButtonText"); private static final String ATTACH_TEXT = UIManager.getString("DockTabbedPane.attachButtonText"); private static final Icon CLOSE_ICON = UIManager.getIcon("DockTabbedPane.menu.close"); private static final Icon CLOSE_ALL_ICON = UIManager.getIcon("DockTabbedPane.closeAll"); private static final Icon CLOSE_OTHER_ICON = UIManager.getIcon("DockTabbedPane.closeAllOther"); private static final Icon ICONIFY_ICON = UIManager.getIcon("DockTabbedPane.menu.hide"); private static final Icon MAXIMIZE_ICON = UIManager.getIcon("DockTabbedPane.menu.maximize"); private static final Icon FLOAT_ICON = UIManager.getIcon("DockTabbedPane.menu.float"); private static final Icon ATTACH_ICON = UIManager.getIcon("DockTabbedPane.menu.attach"); private TabbedContainerActions() { } /** returns an action suitable for closing a dockable contained in a tab. *

* Action properties : The icon is provided, and also the standard localized "close" message. */ public static Action createCloseAction(final Dockable dockable, final DockingDesktop desktop){ AbstractAction action = new AbstractAction(CLOSE_TEXT){ public void actionPerformed(ActionEvent e){ desktop.close(dockable); } }; action.putValue(AbstractAction.SMALL_ICON, CLOSE_ICON); KeyStroke ks = (KeyStroke)UIManager.get("DockingDesktop.closeActionAccelerator"); if (ks != null){ action.putValue(AbstractAction.ACCELERATOR_KEY, ks); } return action; } /** returns an action suitable for closing every dockable contained in a tab. *

* Action properties : The icon is provided, and also an unlocalized "Close all documents" message. */ public static Action createCloseAllAction(final Dockable base, final DockingDesktop desktop){ AbstractAction action = new AbstractAction("Close all documents"){ public void actionPerformed(ActionEvent e){ desktop.closeAllDockablesInTab(base); } }; action.putValue(AbstractAction.SMALL_ICON, CLOSE_ALL_ICON); return action; } /** returns an action suitable for closing every dockable contained in a tab excepted the current one. *

* Action properties : The icon is provided, and also an unlocalized "Close all other documents" message. */ public static Action createCloseAllOtherAction(final Dockable exception, final DockingDesktop desktop){ AbstractAction action = new AbstractAction("Close all other documents"){ public void actionPerformed(ActionEvent e){ desktop.closeAllOtherDockablesInTab(exception); } }; action.putValue(AbstractAction.SMALL_ICON, CLOSE_OTHER_ICON); return action; } /** returns an action suitable for maximizing a dockable contained in a tab. *

* Action properties : The icon is provided, and also a localized "Maximize" message. */ public static Action createMaximizeTabAction(final Dockable dockable, final DockingDesktop desktop){ AbstractAction action = new AbstractAction(MAXIMIZE_TEXT){ public void actionPerformed(ActionEvent e){ desktop.maximize(dockable); } }; action.putValue(AbstractAction.SMALL_ICON, MAXIMIZE_ICON); KeyStroke ks = (KeyStroke)UIManager.get("DockingDesktop.maximizeActionAccelerator"); if (ks != null){ action.putValue(AbstractAction.ACCELERATOR_KEY, ks); } return action; } /** returns an action suitable for hiding a dockable contained in a tab. *

* Action properties : The icon is provided, and also a localized "Iconify" message. */ public static Action createHideTabAction(final Dockable dockable, final DockingDesktop desktop){ AbstractAction action = new AbstractAction(ICONIFY_TEXT){ public void actionPerformed(ActionEvent e){ desktop.setAutoHide(dockable, true); } }; action.putValue(AbstractAction.SMALL_ICON, ICONIFY_ICON); KeyStroke ks = (KeyStroke)UIManager.get("DockingDesktop.dockActionAccelerator"); if (ks != null){ action.putValue(AbstractAction.ACCELERATOR_KEY, ks); } return action; } /** returns an action suitable for floating (detach) a dockable contained in a tab. *

* Action properties : The icon is provided, and a default "Detach" message. */ public static Action createFloatTabAction(final Dockable dockable, final DockingDesktop desktop){ AbstractAction action = new AbstractAction(FLOAT_TEXT){ public void actionPerformed(ActionEvent e){ desktop.setFloating(dockable, true); } }; action.putValue(AbstractAction.SMALL_ICON, FLOAT_ICON); KeyStroke ks = (KeyStroke)UIManager.get("DockingDesktop.floatActionAccelerator"); if (ks != null){ action.putValue(AbstractAction.ACCELERATOR_KEY, ks); } return action; } /** returns an action suitable for attaching a dockable contained in a floating tab. *

* Action properties : The icon is provided, and a default "Attach" message. * @since 2.0.1 */ public static Action createAttachTabAction(final Dockable dockable, final DockingDesktop desktop){ AbstractAction action = new AbstractAction(ATTACH_TEXT){ public void actionPerformed(ActionEvent e){ desktop.setFloating(dockable, false); } }; action.putValue(AbstractAction.SMALL_ICON, ATTACH_ICON); KeyStroke ks = (KeyStroke)UIManager.get("DockingDesktop.floatActionAccelerator"); if (ks != null){ action.putValue(AbstractAction.ACCELERATOR_KEY, ks); } return action; } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/TabbedDockView.java0000644000175000017500000001364010573516350025722 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking; import com.vlsolutions.swing.docking.event.DockDragEvent; import com.vlsolutions.swing.docking.event.DockDropEvent; import com.vlsolutions.swing.docking.event.DockEvent; import java.awt.Component; import javax.swing.SwingUtilities; import javax.swing.UIManager; /** A DockView that can be nested into a TabbedDockableContainer * * @author Lilian Chamontin, VLSolutions */ public class TabbedDockView extends DockView { public TabbedDockView(Dockable dockable) { super(dockable, false); } protected void scanDrop(DockEvent event, boolean drop){ int state = dockable.getDockKey().getDockableState(); if (state == DockableState.STATE_DOCKED) { super.scanDrop(event, drop); } else if (state == DockableState.STATE_FLOATING){ // don't allow drop for floating tabs : only when child of a compound dockable if (DockingUtilities.isChildOfCompoundDockable(dockable)){ super.scanDrop(event, drop); } else { if (drop){ ((DockDropEvent) event).rejectDrop(); } else { ((DockDragEvent) event).delegateDrag(); } } } } public void setVisible(boolean visible){ super.setVisible(visible); if (visible){ if (UIManager.getBoolean("TabbedContainer.requestFocusOnTabSelection")){ // this is a workaround to get focus on a tab when it's selected // obviously, this relies in the fact that the parent of this dockView is // the tab container. SwingUtilities.invokeLater(new Runnable(){ public void run(){ if (getDockable() != null){ Component comp = getDockable().getComponent(); if (comp != null){ comp.requestFocus(); } } } }); } } } } vldocking_2.1.4/src/com/vlsolutions/swing/docking/TabbedDockableContainer.java0000644000175000017500000001261310573516350027555 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.docking; /** Interface describing a container that can be used to display more than * one Dockable in a Tabbed Pane fashion. *

* This interface is meant for API Extenders in order to provide new kinds of * TabbedDockableContainers (the default implementation is DockTabbedPane). * * @author Lilian Chamontin, vlsolutions. * @version 1.0 */ public interface TabbedDockableContainer extends DockableContainer { /** Returns the currently selected (front) dockable */ public Dockable getSelectedDockable(); /** Change the tab selection to display this dockable */ public void setSelectedDockable(Dockable dockable); /** Returs the current tab count (which is also the current dockable count) */ public int getTabCount(); /** Returns the dockable at the index tab */ public Dockable getDockableAt(int index); /** Adds a dockable to the given index tab. */ public void addDockable(Dockable dockable, int index); /** Removes a dockable from the tabs */ public void removeDockable(Dockable dockable); /** Remove the dockable at specified index tab */ public void removeDockable(int index); /** Returns the index of the given dockable */ public int indexOfDockable(Dockable dockable); } vldocking_2.1.4/src/com/vlsolutions/swing/docking/attach16v2.png0000644000175000017500000000047510573516344024640 0ustar twernertwernerPNG  IHDRabKGD pHYs  tIME  +)IDATxc`hTOɓ5"Y` }5_IENDB`vldocking_2.1.4/src/com/vlsolutions/swing/docking/attach16v2rollover.png0000644000175000017500000000051610573516344026421 0ustar twernertwernerPNG  IHDRabKGD pHYs  tIME  TIDATxڝS+0}pj[[Q#~/ܢATW t!Ulg7IR#7{ ?qts+$treyA՘C4*Z/!Q݊H&Rx}OS?uN †144'}0BTI^B94MBB?L|!M"74l/Uk:BIENDB`vldocking_2.1.4/src/com/vlsolutions/swing/docking/close16.gif0000644000175000017500000000152010573516344024202 0ustar twernertwernerGIF89a!,-H*\(0@A !q"Æ-RD(qÏCI`@;vldocking_2.1.4/src/com/vlsolutions/swing/docking/close16pressed.gif0000644000175000017500000000154410573516344025576 0ustar twernertwernerGIF89a!,AH*TxpC .(1!Ŋ(hq#C =~ $ȉ&3 "˓0/V)ѠM;vldocking_2.1.4/src/com/vlsolutions/swing/docking/close16rollover.gif0000644000175000017500000000154410573516344025775 0ustar twernertwernerGIF89a!,AH*TxpC .(1aDbQcƍ3:8#H'A,R$ĕIƄ)ѠM;vldocking_2.1.4/src/com/vlsolutions/swing/docking/close16tab.png0000644000175000017500000000042610573516344024714 0ustar twernertwernerPNG  IHDR w&bKGD pHYs  tIME  WIDATxڝ; 0DEnj9EJct- a}-t wB GFɫvfwVD97Qjc,KSD1a'| U>%' c\x @aպo5&Q n !M)qa>(uD1~.GIT~snN_P^IENDB`vldocking_2.1.4/src/com/vlsolutions/swing/docking/close16tabPressed.png0000644000175000017500000000041610573516344026241 0ustar twernertwernerPNG  IHDR w&bKGD pHYs  tIME  IDATx} 0 D6#dַV)ـ)b*ϱJʛ3Jɫ{@#h擷P̜fζAGgLȱS .yWZO83gp9Rsu1>#9Y9f\΅IENDB`vldocking_2.1.4/src/com/vlsolutions/swing/docking/close16tabRollover.png0000644000175000017500000000036210573516344026440 0ustar twernertwernerPNG  IHDR w&bKGD pHYs  tIME  '[IDATxڝ "M iQJJ0DL^ΰ6<S%`.`.SQUsqќ݀I]:hVGӻ0l6v!+wZȢu7i=~54BjVj&Y{v|C133ػ6E,{}"ÓCPm0"PIENDB`vldocking_2.1.4/src/com/vlsolutions/swing/docking/close16v2pressed.png0000644000175000017500000000042710573516344026064 0ustar twernertwernerPNG  IHDRabKGD pHYs  tIME  CKnIDATxS sNߎV^#=ND%(81c/,bY`*k+'́p*=U-matj(j.VFH!YԛȵVLf)H)S04HZM}?z4Ƭg6O!jZm]PwQIENDB`vldocking_2.1.4/src/com/vlsolutions/swing/docking/close16v2rollover.png0000644000175000017500000000041610573516344026261 0ustar twernertwernerPNG  IHDRabKGD pHYs  tIME  IDATxS ͸]---ZR\ydH^я -ZPd/Ĵ. L}9(D!@9-ZTuѺԜ3ۗ5B$t|ء@$[/n3XY7R%aak V IENDB`vldocking_2.1.4/src/com/vlsolutions/swing/docking/close8.png0000644000175000017500000000034110573516344024142 0ustar twernertwernerPNG  IHDRbKGD pHYs  tIME snIDATxڅ 0 /LAY!k9-#R2-]F0+ҽgctT)A.P iJx/,K[Ulj[S+m'lYQϑp04F,QIENDB`vldocking_2.1.4/src/com/vlsolutions/swing/docking/closeAll16.png0000644000175000017500000000032610573516344024655 0ustar twernertwernerPNG  IHDRabKGD pHYs  tIME"7?tEXtCommentCopyright VLSolutions dD:IDATxc`Tc``"U M.\ff&Z^J 25^&IENDB`vldocking_2.1.4/src/com/vlsolutions/swing/docking/closeAllOther16.png0000644000175000017500000000031210573516344025652 0ustar twernertwernerPNG  IHDRabKGD pHYs  tIME6g!.tEXtCommentCopyright VLSolutions dD.IDATxc`4HlkszN{OzQ{L|MtkǝÞġʜf©ȧģƨŤǺfʯd̫ͯȳӴʹμӾչ]]ԾϺѽ׻ZҽڿXPN)JMGxxtRNS@fbKGDH pHYs  tIME  $iIDATxڅ0 IRh>y~>89dڹ$" |-gÂ&̐!xI5l_ YrPhL0WvN%] ۋVa8gpWten`Eyg0/GZMPwa-y pS8I:?wx]= !"IENDB`vldocking_2.1.4/src/com/vlsolutions/swing/docking/dock16.gif0000644000175000017500000000152310573516344024020 0ustar twernertwernerGIF89a!,0H*\H0C  -b<Ç 7Vd8ɓ$;vldocking_2.1.4/src/com/vlsolutions/swing/docking/dock16pressed.gif0000644000175000017500000000154610573516344025413 0ustar twernertwernerGIF89a΄B!,CH" aHp!(B@Ń1j#CS~$cCWn›8 ;vldocking_2.1.4/src/com/vlsolutions/swing/docking/dock16rollover.gif0000644000175000017500000000154310573516344025607 0ustar twernertwernerGIF89aB!,@H"!Hp!^xQ#Ǝ1~drɊn$Q(6tI;vldocking_2.1.4/src/com/vlsolutions/swing/docking/dock16v2.png0000644000175000017500000000036210573516344024307 0ustar twernertwernerPNG  IHDRabKGD pHYs  tIME  /zpIDATxc``KKK=. 555|\ ޿``xqC>YZa@} 6y&|x8 3000H(Vc !BаVRuz|ޢ},|1!GtIENDB`vldocking_2.1.4/src/com/vlsolutions/swing/docking/dock16v2pressed.png0000644000175000017500000000037610573516344025702 0ustar twernertwernerPNG  IHDRabKGD pHYs  tIME  QIDATxc@!lN85T&V]NN޿``xq0w, @R\7u!$<~AP$Q[RF*Cj[#hIB?8,٢;`2B2IENDB`vldocking_2.1.4/src/com/vlsolutions/swing/docking/dock16v2rollover.png0000644000175000017500000000036510573516344026077 0ustar twernertwernerPNG  IHDRabKGD pHYs  tIME  ,IWMIDATxc@!lN8U NN C?00J,-B 2  XM\4ۇmCj[O\_,s>F.% +PIENDB`vldocking_2.1.4/src/com/vlsolutions/swing/docking/dragcursor.gif0000644000175000017500000000162210573516344025104 0ustar twernertwernerGIF89a !, oH*\ȰÇ#JHŋƎ7B ɓ&EBDɲD-Qt3fJ6Oys$ϒ3gP5se8(ϥ A~*ƫXjʵׯ;vldocking_2.1.4/src/com/vlsolutions/swing/docking/float16v2.png0000644000175000017500000000051110573516344024470 0ustar twernertwernerPNG  IHDRabKGD pHYs  tIME  ɥIDATxڝS+ }؊\ "Et\&T"!J~}͒}Zo\3!>l{X [S(pPJsJY;ð8gPJԍaA# Ę)B*$11Iܜ4ѽyO!~`)a-PSH{4hsC%7Q" O(UIENDB`vldocking_2.1.4/src/com/vlsolutions/swing/docking/float16v2pressed.png0000644000175000017500000000052210573516344026060 0ustar twernertwernerPNG  IHDRabKGD pHYs  tIME  50IDATxڝ!0D7 w؊:-q u$ i$aYKw؜ ҵXh]!Ŵںx0󠤊L΍GزnfH2pO}~'۔:IENDB`vldocking_2.1.4/src/com/vlsolutions/swing/docking/maximize16v2pressed.png0000644000175000017500000000050210573516344026574 0ustar twernertwernerPNG  IHDRabKGD pHYs  tIME  XRgIDATxڥR \k @[VZ{@Kf'M6 =w9 P&P &K fѯ9ߪd(D/fBR*?z t 'R?>jDVDiBVXNxA} 9pgv{J1vnyT0=Jb=RIl|۸rGp0?ªxHIENDB`vldocking_2.1.4/src/com/vlsolutions/swing/docking/maximize16v2rollover.png0000644000175000017500000000045310573516344027000 0ustar twernertwernerPNG  IHDRabKGD pHYs  tIME  -GaIDATxڥS 0 5'Yoбܡ( :@%$eSJ4 R&[q6- a=I/ݵwťL

VLSolutions Docking Framework.

This javadoc directory represents the API documentation of the VL Docking Framework.

Original javadoc website is www.vlsolutions.com

Getting Started

To fully understand the principles of docking please read the following documents :
  • {@link com.vlsolutions.swing.docking main package summary}
  • online developer's tutorial
  • and the javadoc of main classes ({@link com.vlsolutions.swing.docking.DockingDesktop DockingDesktop} / {@link com.vlsolutions.swing.docking.DockKey DockKey} / {@link com.vlsolutions.swing.docking.Dockable Dockable}).

For those who would like to extend the API, please read this javadoc and don't hesitate to contact vlsolutions by email at support@vlsolutions.com for explanations. vldocking_2.1.4/src/com/vlsolutions/swing/docking/package.html0000644000175000017500000001775610573516344024542 0ustar twernertwerner

The VL Docking Framework for JFC "Swing" applications.

Goals.

The VLSolutions Docking Framework provides a means to add docking capabilities into a Swing application with minor modification of the components hierarchy (only decoration of existing components and containers and adding of a new root container).

Audience.

This javadoc is targetted to :

  • API Users : developpers of "User Applications"
  • API Extenders : developpers that want to extend the framework, add new kinds of containers, or change the look and feel of existing ones.

You will find in this documentation references of those targets, indicating you if you have to read such document or not, depending on your goals (developping a "User Application" or extending the API).

For API Users

Basic Description

The VL Docking Framework is a set of Swing Components that is used to enhance any Swing Application by providing Docking capabilities to user components :

A user component can be any Swing JComponent (usualy a JPanel or a JScrollPane).

Docking functions are built upon the following classes :

  • DockingDesktop : the root container of a docking-enabled application
  • Dockable : an interface implemented (usually) by components that need docking capabilities.
  • DockableContainers : specialized containers with drag and drop extensions (come in two flavors, SingleDockableContainer and TabbedDockabeContainer).
  • DockKey : a JavaBeans object fully describing the dockable (use for save/load, and for DockableContainers customization) : name, icon, tooltip, docking features.

The DockingDesktop class.

There is usually only one DockingDesktop associated to a Window.

For developpers used to JInternalFrame API, the DockingDesktop is equivalent to the JDesktopPane : a layered pane capable of managing and displaying multiple components, with overlapping when needed.

The desktop is composed of :

  • 4 auto-hide zones (on borders ) displaying buttons that are used to activate or hide their Dockable.
  • a central zone, for visible Dockables (or "docked" components).

The central zone contains a DockableContainer that can be recursively splitted in two (horizontally or vertically) to add more DockableContainers. Each split acts as a JSplitPane, and can be resized by the end-user or with the API.

The Dockable interface

The Dockable is implemented by dockable component providers or, simply by components that want to benefit of the docking features.

If you already have a working application (without docking) and want to use the docking framework, take your GUI major components, have them implement the Dockable interface (only 2 methods) and you will be able to add them to the docking desktop.

Alternatively, you can use DockablePanel which is a JPanel container implementing Dockable.

The DockableContainer, SingleDockableContainer and TabbedDockableContainer interfaces.

These interfaces are implemented by containers of Dockables. Usually you will not interact with them (except if you want to extend the framework).

The DockKey class

This one is important because it fully describes the Docking presentation of your dockables, and their behaviour.

A DockKey is used in 3 situations :

  • the DockingDesktop needs a unique key to identify a dockable (for read/write operations)
  • the DockableContainer displaying a Dockable wants information about the dockable : a name, an icon, ...
  • and finally, the DockingDesktop and DockableContainer only allow docking features associated to that DockKey (maximizeable, closeable, hidable...).

So keep in mind that each dockable must have a unique DockKey (it's a kind of primary key) and that the key, as a javabean, is used to decorate the dockable container.

Listeners : most DockKey properties are bound, and changing their value will have an immediate effect on the DockingDesktop : for example, you can change the icon property of a key and it will be propagated to the DockableContainer's title bar of its dockable.


Getting Started

It's easy, just follow the steps below, or have a look at the tutorial on www.vlsolutions.com/en/documention/docking/tutorial.

Creating a small sample application :

Here is a working code showing a simple frame with dockable buttons.

import com.vlsolutions.swing.docking.*;
import javax.swing.*;
import java.awt.*;

public class DemoFrame extends JFrame {
  // our docking desktop
  DockingDesktop desk = new DockingDesktop();

  public DemoFrame(){
    setDefaultCloseOperation(DISPOSE_ON_CLOSE);
    getContentPane().add(desk);

    // first, create 4 dockable buttons (inner class below)
    DockableButton button1 = new DockableButton("Dockable 1");
    DockableButton button2 = new DockableButton("Dockable 2");
    DockableButton button3 = new DockableButton("Dockable 3");
    DockableButton button4 = new DockableButton("Dockable 4");
    // first button at center
    desk.addDockable(button1);

    // second and third button splitted vertically on the left of center
    // first parameter is the "reference", second is the added dockable
    desk.split(button1, button2, DockingConstants.SPLIT_LEFT);
    desk.split(button2, button3, DockingConstants.SPLIT_BOTTOM);

    // add the fourth button as a tab on the 3rd :
    desk.createTab(button3, button4, 1);

    SwingUtilities.invokeLater(
        new Runnable() {
      public void run() {
        setSize(800,600);
        validate();
        setVisible(true); // realize on the event dispatch thread

      }
    });
  }
  public static void main(String [] args){
    new DemoFrame();
  }

  // our basic dockable object
  class DockableButton extends JButton implements Dockable {
     DockKey key;
     public DockableButton(String label){
        super(label);
        this.key = new DockKey(label); // most simple dockkey constructor
        setPreferredSize(new Dimension(200,200));
     }

    public DockKey getDockKey() {
      return key;
    }

    public Component getComponent() {
      return this;
    }
  }
}

But of course, there's more in the docking framework than this. For example you can also :

  • hide a component on a border
  • attract user attention by a blinking dockable title
  • adjust the width and height of the dockables
  • read and write a desktop configuration from/to an XML stream
  • ...
You can read more about these features in the tutorial on www.vlsolutions.com/en/documention/docking/tutorial.

Browsing the API

The subset of classes of this package needed to understand and use the Docking Framework is limited to the following classes :

  • DockingPanel : the panel that contains the users components is also the main interface to docking functions.
  • Dockable : the interface implemented by dockable objects
  • DockKey : the key of a Dockable, an object that describes a user component (icon, text, tooltip)

Extending the API

This API has been developed with extension in mind.

To Fully understand its principles, you will have to browse the entire javadoc and read the API extension tutorial on www.vlsolutions.com. vldocking_2.1.4/src/com/vlsolutions/swing/docking/restore16.gif0000644000175000017500000000153210573516344024563 0ustar twernertwernerGIF89a!,7H :< ąVǁ5flh1D)6Ȳe€;vldocking_2.1.4/src/com/vlsolutions/swing/docking/restore16pressed.gif0000644000175000017500000000157610573516344026161 0ustar twernertwernerGIF89aBBB΄B!,[H@ Dx@B #B4r8pdH O8q#K cʜRK&EPȄ3xbˉD)p;vldocking_2.1.4/src/com/vlsolutions/swing/docking/restore16rollover.gif0000644000175000017500000000156210573516344026353 0ustar twernertwernerGIF89aBBBB!,OH@ DxP@Bp8pņ qcBbI S\ycK'8RG-rØ7\I0 ;vldocking_2.1.4/src/com/vlsolutions/swing/docking/restore16v2.png0000644000175000017500000000050310573516344025047 0ustar twernertwernerPNG  IHDRabKGD pHYs  tIME  %s~IDATxS;0 }YrkBre ٺ2CP:m?O~fnAc,b0\ھ "ReE]M,"?McEށDyTOWVb3PpYL˒E d<֧ιF۰?nOrs޻EJ&ny">a<݀Xv&IENDB`vldocking_2.1.4/src/com/vlsolutions/swing/docking/restore16v2pressed.png0000644000175000017500000000053110573516344026436 0ustar twernertwernerPNG  IHDRabKGD pHYs  tIME  nmIDATxڥS ExZضmw7w #~f4ބ! * As JTabbedPanes cannot use any JComponents as tab selectors (the access if protected and we just have * a label, an icon and a tooltip), we have to rely on tricks to bypass them. * * * * @author Lilian Chamontin, VLSolutions * @update 2005/11/01 Lilian Chamontin : fixed NPE when otherIcons == null (tabs without smart icons) * @update 2005/11/08 Lilian Chamontin : fixed bug related to event management when multiple other-icons are used * (big thanks to Emmanuel GAUVRIT). * @update 2005/11/21 Lilian Chamontin : enhanced width calculation of the icon size. */ public class JTabbedPaneSmartIcon implements Icon, Cloneable { /* Implementation : This icon is larger than standard icons : it also paints the tab title and optional buttons. * Inner Event management (with JTabbedPaneSmartIconManager) allows simulation of action on the buttons. * */ /** The traditional tab selector icon */ private Icon icon; /** calculated used width (icon + label + other icons) + gaps */ private int width; /** x location where the other icons are drawn*/ private int otherIconsOffset; /** tab height */ private int height; /** the traditional tab selector label */ private String label; /** the traditional tab selector tooltip text*/ private String tooltipText; /** local tooltip text : the one to use during mouse movements (depends on the mouse position, * and can be either the tab selector tooltip text or one of the smart buttons included into this icon). */ private String localTooltipText; // list of additional icons (presented as buttons) private SmartIconJButton [] otherIcons; /** currently pressed inner button */ private SmartIconJButton pressedButton; /** currently rolled-over inner button */ private SmartIconJButton rolloverButton; /** gap between the icon and the text*/ private int textIconGap; /** gap between the text and the following icons*/ private int otherIconsGap; private boolean antialiased = false; /* The container this icon is for (required to calculate proper widths and heights) */ private JTabbedPane container; private int inBetweenOtherIconsGap; /** Constructs a new smart icon with a given set of additional buttons */ public JTabbedPaneSmartIcon(Icon icon, String label, SmartIconJButton [] otherIcons) { this.icon = icon; this.label = label; this.otherIcons = otherIcons; this.textIconGap = UIManager.getInt("TabbedPane.textIconGap"); this.otherIconsGap = UIManager.getInt("TabbedPane.otherIconsGap"); this.inBetweenOtherIconsGap = UIManager.getInt("TabbedPane.inBetweenOtherIconsGap"); invalidateSize(); try { //mimic the unofficial aa settings of Swing this.antialiased = "true".equals(System.getProperty("swing.aatext")); } catch (SecurityException ignore){ // for untrusted web start apps failing gracefully } } public SmartIconJButton getSmartButton(int index){ return otherIcons[index]; } public void setSmartButton(int index, SmartIconJButton btn){ otherIcons[index] = btn; invalidateSize(); } /** Creates a shalow copy of this icon */ public JTabbedPaneSmartIcon copy(){ return (JTabbedPaneSmartIcon) clone(); } /** {@inheritDoc} */ public Object clone(){ try { return super.clone(); } catch (CloneNotSupportedException ignore){ ignore.printStackTrace(); return null; } } /** Update the tooltip of this icon */ public void setTooltipText(String tooltip){ this.tooltipText = tooltip; } /** Return the tooltip of this icon */ public String getTooltipText(){ return this.tooltipText; } /** Return the local tooltip of this icon (the one associated with inner mouse movements)*/ public String getLocalTooltipText(){ return this.localTooltipText; } /** Update the label to be displayed on the tab */ public void setLabel(String label){ this.label = label; invalidateSize(); } /** Return the tab label */ public String getLabel(){ return this.label; } /** Update the main icon (left) to be displayed on the tab */ public void setIcon(Icon icon){ this.icon = icon; invalidateSize(); } /** Return the tab icon */ public Icon getIcon(){ return this.icon; } private void invalidateSize(){ this.width = this.height = -1; } /** Specify which container will use this icon. *

If the icon is shared between containers, please provide at least one as * this allows the icon to properly estimate its dimension. */ public void setIconForTabbedPane(JTabbedPane container){ this.container = container; } /** paints the icon (and the associated label and sub-icons) */ public void paintIcon(Component c, Graphics g, int x, int y) { Graphics2D g2 = (Graphics2D) g; Object renderingValue = null; if (this.antialiased){ renderingValue = g2.getRenderingHint(RenderingHints.KEY_ANTIALIASING); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); } if (icon != null){ icon.paintIcon(c, g, x, y); } Font f = UIManager.getFont("JTabbedPaneSmartIcon.font"); // 2006/01/23 if (f != null){ g.setFont(f); } // reevaluate the width with correct graphics object, in case something has changed FontMetrics fm = g.getFontMetrics(); int iconsOffset = otherIconsOffset; if (icon != null){ g.drawString(label, x+icon.getIconWidth() + textIconGap, y + height - fm.getDescent()); } else { g.drawString(label, x, y + height - fm.getDescent()); } if (otherIcons != null){ //2005/11/01 for (int i=0; i < otherIcons.length; i++){ otherIcons[i].paintIcon(c, g, x + iconsOffset, y + height / 2 - otherIcons[i].getIconHeight()/2); iconsOffset += otherIcons[i].getIconWidth(); if (i < otherIcons.length-1){ iconsOffset+= inBetweenOtherIconsGap; } } } if (antialiased){ g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, renderingValue); } } private SmartIconJButton findButtonAt(Point p){ int start = otherIconsOffset; if (otherIcons != null){ //2005/11/01 for (int i=0; i < otherIcons.length; i++){ SmartIconJButton btn = otherIcons[i]; if (p.x >= start && p.x < start + btn.getIconWidth()){ if (p.y >= height/2 - btn.getIconHeight() /2 && p.y < height/2 + btn.getIconHeight() /2){ return btn; } else { return null; } } start += btn.getIconWidth(); // bug corrected thanks to Emmanuel GAUVRIT 2005/11/08 if (i < otherIcons.length-1){ start += inBetweenOtherIconsGap; } } } return null; } /** Returns the width of this icon */ public int getIconWidth() { if (width == -1){ if (container == null){ throw new NullPointerException("container for this smart icon not specified with setIconForTabbedPane()"); } // reevaluate the width with correct graphics object, in case something has changed //Font f = UIManager.getFont("DockTabbedPane.font"); // 2006/01/23 Font f = UIManager.getFont("JTabbedPaneSmartIcon.font"); // 2006/01/23 FontMetrics fm = container.getFontMetrics(f); this.width = 0; if (icon != null){ width = icon.getIconWidth(); } width += textIconGap + fm.stringWidth(label) + otherIconsGap; this.otherIconsOffset = width; int iconsOffset = otherIconsOffset; if (otherIcons != null){ for (int i=0; i < otherIcons.length; i++){ width += otherIcons[i].getIconWidth(); // additional width for icons if (i < otherIcons.length-1){ width += inBetweenOtherIconsGap; } } } } return width; } /** Returns the height of this icon */ public int getIconHeight() { if (height == -1){ if (icon != null){ height = icon.getIconHeight(); } else { height = 16; // standard height (as if there was an icon) : should be calculated instead of fixed } } return height; } /** Process the mouse pressed event. *

* Mouse coordinates are given relative to this icon */ public boolean onMousePressed(MouseEvent e){ // find the icon under the point SmartIconJButton btn = findButtonAt(e.getPoint()); if (btn != null && btn.isEnabled()){ btn.setPressed(true); pressedButton = btn; return true; } return false; } /** Process the mouse released event. *

* Mouse coordinates are given relative to this icon */ public boolean onMouseReleased(final MouseEvent e){ if (pressedButton != null && pressedButton.isEnabled()){ pressedButton.setPressed(false); final SmartIconJButton btn = findButtonAt(e.getPoint()); if (btn == pressedButton){ btn.fireAction(new ActionEvent(e.getSource(), ActionEvent.ACTION_PERFORMED, "" )); return true; } } return false; } /** Process the mouse exited event. *

* Mouse coordinates are given relative to this icon */ public boolean onMouseExited(MouseEvent e){ // reset all rollover states if (rolloverButton != null){ rolloverButton.setRollover(false); rolloverButton = null; localTooltipText = tooltipText; return true; } rolloverButton = null; return false; } /** Process the mouse moved event. *

* Mouse coordinates are given relative to this icon */ public boolean onMouseMoved(MouseEvent e){ // check for a rollover effect SmartIconJButton btn = findButtonAt(e.getPoint()); boolean shouldRepaint = false; if (btn != null){ String tip = btn.getTooltipText(); if (tip != null){ if (!tip.equals(localTooltipText)){ this.localTooltipText = tip; shouldRepaint = true; } } else if (localTooltipText != tooltipText){ this.localTooltipText = tooltipText; shouldRepaint = true; } if (btn == rolloverButton){ // still on the same button } else { // another button if (rolloverButton != null){ rolloverButton.setRollover(false); } rolloverButton = btn; rolloverButton.setRollover(true); shouldRepaint = true; } } else if (rolloverButton != null){ rolloverButton.setRollover(false); rolloverButton = null; localTooltipText = tooltipText; shouldRepaint = true; } return shouldRepaint; } } vldocking_2.1.4/src/com/vlsolutions/swing/tabbedpane/JTabbedPaneSmartIconManager.java0000644000175000017500000003746110573516350030775 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.tabbedpane; import java.awt.Component; import java.awt.Point; import java.awt.Rectangle; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import javax.swing.Icon; import javax.swing.JTabbedPane; import javax.swing.SwingUtilities; /** This class is the interface between a JTabbedPane and a smart icon. *

* As JTabbedPanes cannot use any JComponents as tab selectors (the access if protected and we just have * a label, an icon and a tooltip), we have to rely on tricks to bypass them. *

* This class is used (with a mouse listener) to forward events into the smart icon. which is responsible * for faking an enhanced tab selector (including label and optional buttons). * * * @author Lilian Chamontin, VLSolutions */ public class JTabbedPaneSmartIconManager implements MouseListener, MouseMotionListener { private JTabbedPane tabbedPane; private JTabbedPaneSmartIcon pressedIcon; private int pressedTab; // the tab associated to the pressed icon private JTabbedPaneSmartIcon movedIcon; private int movedTab; /** Constructs a new tabbedPane manager for a given JTabbedPane */ public JTabbedPaneSmartIconManager(JTabbedPane tabbedPane) { this.tabbedPane = tabbedPane; tabbedPane.addMouseListener(this); tabbedPane.addMouseMotionListener(this); } /** MouseListener implementation, use to track mouse behaviour inside the tab selector bounds * and forward them to the appropriate smart icon. */ public void mouseReleased(MouseEvent e) { checkTabCount(); // forward the event to the pressed smart icon if (pressedIcon != null){ Point p = e.getPoint(); final Rectangle r = tabbedPane.getBoundsAt(pressedTab); Point iPoint = convertPointToIcon(r, p, pressedIcon); final MouseEvent eSmart = new MouseEvent( (Component) e.getSource(), e.getID(), e.getWhen(), e.getModifiers(), iPoint.x, iPoint.y, e.getClickCount(), e.isPopupTrigger(), e.getButton()); try { if (pressedIcon.onMouseReleased(eSmart)){ tabbedPane.repaint(r.x, r.y, r.width, r.height); // no choice but trigger a repaint } } catch (Exception ignore){ // bug database : 5075526 this is to remove the stack trace } pressedIcon = null; } } private Point convertPointToIcon(Rectangle r, Point p, Icon icon){ int x = p.x - (r.x + r.width/2 - icon.getIconWidth()/2) ; int y = p.y - (r.y + r.height/2 - icon.getIconHeight()/2); return new Point(x, y); } /** MouseListener implementation, use to track mouse behaviour inside the tab selector bounds * and forward them to the appropriate smart icon. */ public void mousePressed(MouseEvent e) { // where is the mouse pressed ? Point p = e.getPoint(); this.pressedIcon = null; // reset the pressed state int targetTab = findTabAt(p); if (targetTab != -1){ Icon icon = tabbedPane.getIconAt(targetTab); if (icon instanceof JTabbedPaneSmartIcon){ JTabbedPaneSmartIcon smartIcon = (JTabbedPaneSmartIcon) icon; // convert point into smartIcon coordinates // get the tab bounds Rectangle r = tabbedPane.getBoundsAt(targetTab); // as the icon is the only thing visible, we consider it centered in the tab // (which is the default paint behaviour of BasicTabbedPaneUI, and should be okay // with most look and feels. int x = p.x - (r.x + r.width/2 - icon.getIconWidth()/2) ; int y = p.y - (r.y + r.height/2 - icon.getIconHeight()/2); if (x >=0 && y >= 0 && x < icon.getIconWidth() && y < icon.getIconHeight()){ // forward the event to the smart icon MouseEvent eSmart = new MouseEvent( (Component) e.getSource(), e.getID(), e.getWhen(), e.getModifiers(), x, y, e.getClickCount(), e.isPopupTrigger(), e.getButton()); if (smartIcon.onMousePressed(eSmart)){ tabbedPane.repaint(r.x, r.y, r.width, r.height); // no choice but trigger a repaint } pressedIcon = smartIcon; pressedTab = targetTab; } } } } /** verify if the tab count hasn't changed. *

* There is always the risk that the last tab has been removed (and movedTab will be * out of bounds) * */ private void checkTabCount(){ if (movedTab >= tabbedPane.getTabCount()){ // too late : tab has been removed movedTab = -1; movedIcon = null; } if (pressedTab >= tabbedPane.getTabCount()){ pressedTab = -1; pressedIcon = null; } } private int findTabAt(Point p){ int x= p.x; int y = p.y; for (int i=0; i < tabbedPane.getTabCount(); i++){ if (tabbedPane.getBoundsAt(i).contains(x, y)){ return i; } } return -1; } /** MouseListener implementation, use to track mouse behaviour inside the tab selector bounds * and forward them to the appropriate smart icon. */ public void mouseMoved(MouseEvent e) { checkTabCount(); // where is the mouse moved ? Point p = e.getPoint(); int targetTab = findTabAt(p); if (targetTab != -1){ Icon icon = tabbedPane.getIconAt(targetTab); if (icon instanceof JTabbedPaneSmartIcon){ JTabbedPaneSmartIcon smartIcon = (JTabbedPaneSmartIcon) icon; if (movedIcon != null && movedIcon != smartIcon){ // trigger a mouseExit from the movedIcon Rectangle prevRect = tabbedPane.getBoundsAt(movedTab); Point iPoint = convertPointToIcon(prevRect, p, movedIcon); MouseEvent eSmart = new MouseEvent( (Component) e.getSource(), MouseEvent.MOUSE_EXITED, e.getWhen(), e.getModifiers(), iPoint.x, iPoint.y, e.getClickCount(), e.isPopupTrigger(), e.getButton()); if (movedIcon.onMouseExited(eSmart)){ String tip = movedIcon.getLocalTooltipText(); if (tip != null && ! tip.equals(tabbedPane.getToolTipTextAt(targetTab))){ tabbedPane.setToolTipTextAt(targetTab, tip); } // tabbedPane.repaint(prevRect.x, prevRect.y, prevRect.width, prevRect.height); tabbedPane.revalidate(); tabbedPane.repaint(); } movedIcon = null; movedTab = -1; } // convert point into smartIcon coordinates // get the tab bounds Rectangle r = tabbedPane.getBoundsAt(targetTab); Point iPoint = convertPointToIcon(r, p, icon); if (iPoint.x >=0 && iPoint.y >= 0 && iPoint.x < icon.getIconWidth() && iPoint.y < icon.getIconHeight()){ // forward the event to the smart icon MouseEvent eSmart = new MouseEvent( (Component) e.getSource(), e.getID(), e.getWhen(), e.getModifiers(), iPoint.x, iPoint.y, e.getClickCount(), e.isPopupTrigger(), e.getButton()); if (smartIcon.onMouseMoved(eSmart)){ String tip = smartIcon.getLocalTooltipText(); if (tip != null && ! tip.equals(tabbedPane.getToolTipTextAt(targetTab))){ tabbedPane.setToolTipTextAt(targetTab, tip); } tabbedPane.revalidate(); tabbedPane.repaint(); // tabbedPane.repaint(r.x, r.y, r.width, r.height); } movedIcon = smartIcon; movedTab = targetTab; } else { // in tab, but not on icon if (movedIcon != null){ // trigger a mouseExit from the movedIcon Rectangle prevRect = tabbedPane.getBoundsAt(movedTab); iPoint = convertPointToIcon(prevRect, p, movedIcon); MouseEvent eSmart = new MouseEvent( (Component) e.getSource(), MouseEvent.MOUSE_EXITED, e.getWhen(), e.getModifiers(), iPoint.x, iPoint.y, e.getClickCount(), e.isPopupTrigger(), e.getButton()); if (movedIcon.onMouseExited(eSmart)){ String tip = movedIcon.getLocalTooltipText(); if (tip != null && ! tip.equals(tabbedPane.getToolTipTextAt(targetTab))){ tabbedPane.setToolTipTextAt(targetTab, tip); } tabbedPane.revalidate(); tabbedPane.repaint(); // tabbedPane.repaint(prevRect.x, prevRect.y, prevRect.width, prevRect.height); } } movedIcon = null; movedTab = -1; } } else { // not a smart icon ? if (movedIcon != null){ // trigger a mouseExit from the movedIcon Rectangle prevRect = tabbedPane.getBoundsAt(movedTab); Point iPoint = convertPointToIcon(prevRect, p, movedIcon); MouseEvent eSmart = new MouseEvent( (Component) e.getSource(), MouseEvent.MOUSE_EXITED, e.getWhen(), e.getModifiers(), iPoint.x, iPoint.y, e.getClickCount(), e.isPopupTrigger(), e.getButton()); if (movedIcon.onMouseExited(eSmart)){ String tip = movedIcon.getLocalTooltipText(); if (tip != null && ! tip.equals(tabbedPane.getToolTipTextAt(targetTab))){ tabbedPane.setToolTipTextAt(targetTab, tip); } tabbedPane.revalidate(); tabbedPane.repaint(); // tabbedPane.repaint(prevRect.x, prevRect.y, prevRect.width, prevRect.height); } movedIcon = null; movedTab = -1; } } } else { // not on a tab if (movedIcon != null){ // trigger a mouseExit from the movedIcon Rectangle prevRect = tabbedPane.getBoundsAt(movedTab); Point iPoint = convertPointToIcon(prevRect, p, movedIcon); MouseEvent eSmart = new MouseEvent( (Component) e.getSource(), MouseEvent.MOUSE_EXITED, e.getWhen(), e.getModifiers(), iPoint.x, iPoint.y, e.getClickCount(), e.isPopupTrigger(), e.getButton()); if (movedIcon.onMouseExited(eSmart)){ String tip = movedIcon.getLocalTooltipText(); if (tip != null && ! tip.equals(tabbedPane.getToolTipTextAt(movedTab))){ tabbedPane.setToolTipTextAt(movedTab, tip); } tabbedPane.revalidate(); tabbedPane.repaint(); // tabbedPane.repaint(prevRect.x, prevRect.y, prevRect.width, prevRect.height); } movedIcon = null; movedTab = -1; } } } /** MouseListener implementation, use to track mouse behaviour inside the tab selector bounds * and forward them to the appropriate smart icon. */ public void mouseExited(MouseEvent e) { checkTabCount(); if (movedIcon != null){ Point p = e.getPoint(); // trigger a mouseExit from the movedIcon Rectangle prevRect = tabbedPane.getBoundsAt(movedTab); Point iPoint = convertPointToIcon(prevRect, p, movedIcon); MouseEvent eSmart = new MouseEvent( (Component) e.getSource(), MouseEvent.MOUSE_EXITED, e.getWhen(), e.getModifiers(), iPoint.x, iPoint.y, e.getClickCount(), e.isPopupTrigger(), e.getButton()); if (movedIcon.onMouseExited(eSmart)){ String tip = movedIcon.getLocalTooltipText(); if (tip != null && ! tip.equals(tabbedPane.getToolTipTextAt(movedTab))){ tabbedPane.setToolTipTextAt(movedTab, tip); } tabbedPane.repaint(prevRect.x, prevRect.y, prevRect.width, prevRect.height); } movedIcon = null; movedTab = -1; } } /** MouseListener implementation, not used. */ public void mouseEntered(MouseEvent e) { } /** MouseMotionListener implementation, not used. */ public void mouseDragged(MouseEvent e) { } /** MouseListener implementation, not used. */ public void mouseClicked(MouseEvent e) { } } vldocking_2.1.4/src/com/vlsolutions/swing/tabbedpane/SmartIconJButton.java0000644000175000017500000002536310573516350026766 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.tabbedpane; import java.awt.Color; import java.awt.Graphics; import java.awt.Image; import java.awt.event.ActionEvent; import java.awt.image.BufferedImage; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.GrayFilter; import javax.swing.Icon; import javax.swing.ImageIcon; /** A sub component of JTabbedPaneSmartIcon, used to describe a button included in a tabbedpane. *

* As JTabbedPanes cannot use any JComponents as tab selectors (the access if protected and we just have * a label, an icon and a tooltip), we have to rely on tricks to bypass them. *

* This trick, the SmartIconJButton is an icon faking the behaviour of a button. It uses an Action * for reacting to clicks and manages a set of images (default, rollover, pressed, disabled) to * behave like a rollover button. * * @author Lilian Chamontin, VLSolutions */ public class SmartIconJButton implements Icon, PropertyChangeListener { /** The action triggered when the clicks on the icon */ protected Action action; /** the default icon (enabled/visible)*/ protected Icon defaultIcon; /** the icon for the rollover effect*/ protected Icon rolloverIcon; /** the icno for the pressed effect */ protected Icon pressedIcon; /** the icon for the disabled effect */ protected Icon disabledIcon; /** the tooltip associated with the button */ protected String tooltipText; /* internal state variables*/ private boolean isRollover, isPressed, isEnabled, isVisible; /** Constructs a new button with an action. * * The button is enabled and visible. */ public SmartIconJButton(Action action) { this.action = action; defaultIcon = (Icon) action.getValue(AbstractAction.SMALL_ICON); tooltipText = (String) action.getValue(AbstractAction.SHORT_DESCRIPTION); isVisible = true; isEnabled = action.isEnabled(); action.addPropertyChangeListener(this); } /** Update the default icon property */ public void setIcon(Icon icon){ this.defaultIcon = icon; } /** Returns the default icon */ public Icon getIcon(){ return defaultIcon; } /** Update the rollover icon property */ public void setRolloverIcon(Icon icon){ this.rolloverIcon = icon; } /** Returns the rollover icon */ public Icon getRolloverIcon(){ return rolloverIcon; } /** Update the pressed icon property */ public void setPressedIcon(Icon icon){ this.pressedIcon = icon; } /** Returns the pressed icon */ public Icon getPressedIcon(){ return pressedIcon; } /** Update the disabled icon property */ public void setDisabledIcon(Icon icon){ this.disabledIcon = icon; } /** Returns the disabled icon */ public Icon getDisabledIcon(){ return disabledIcon; } /** Update the rollover state */ public void setRollover(boolean isRollover){ this.isRollover = isRollover; } /** Update the enabled state */ public void setEnabled(boolean isEnabled){ this.isEnabled = isEnabled; } /** Update the visible state */ public void setVisible(boolean isVisible){ this.isVisible = isVisible; } /** Update the pressed state */ public void setPressed(boolean isPressed){ this.isPressed = isPressed; } /** Returns the rollover state*/ public boolean isRollover(){ return isRollover; } /** Returns the pressed state*/ public boolean isPressed(){ return isPressed; } /** Returns the enabled state*/ public boolean isEnabled(){ return isEnabled; } /** Returns the visible state*/ public boolean isVisible(){ return isVisible; } /** paints the appropriate icon according to its internal state (pressed, rollover...) */ public void paintIcon(java.awt.Component c, java.awt.Graphics g, int x, int y) { if (! isVisible){ return; } else if (isEnabled){ if (isPressed){ if (pressedIcon != null){ pressedIcon.paintIcon(c, g, x, y); } else { defaultIcon.paintIcon(c, g, x+1, y+1); } } else if (isRollover){ if (rolloverIcon != null){ rolloverIcon.paintIcon(c, g, x, y); } else { defaultIcon.paintIcon(c, g, x-1, y-1); // "push" effect } } else { // just the default if (defaultIcon != null){ defaultIcon.paintIcon(c, g, x, y); } } } else { // disabled if (disabledIcon == null){ disabledIcon = createDisabledIcon(); } disabledIcon.paintIcon(c,g, x, y); } } private Icon createDisabledIcon(){ if (defaultIcon instanceof ImageIcon){ Image i = GrayFilter.createDisabledImage (((ImageIcon)defaultIcon).getImage()); return new ImageIcon(i); } else { BufferedImage bi = new BufferedImage(defaultIcon.getIconWidth(), defaultIcon.getIconHeight(), BufferedImage.TYPE_INT_ARGB); Graphics g = bi.createGraphics(); g.setColor(new Color(0,0,0,0)); g.fillRect(0,0, defaultIcon.getIconWidth(), defaultIcon.getIconHeight()); defaultIcon.paintIcon(null, g, 0,0); g.dispose(); Image i = GrayFilter.createDisabledImage(bi); return new ImageIcon(i); } } public int getIconWidth() { int w = 0; if (defaultIcon != null){ w = Math.max(w, defaultIcon.getIconWidth()); } if (rolloverIcon != null){ w = Math.max(w, rolloverIcon.getIconWidth()); } if (pressedIcon != null){ w = Math.max(w, pressedIcon.getIconWidth()); } return w; } public int getIconHeight() { int h = 0; if (defaultIcon != null){ h = Math.max(h, defaultIcon.getIconHeight()); } if (rolloverIcon != null){ h = Math.max(h, rolloverIcon.getIconHeight()); } if (pressedIcon != null){ h = Math.max(h, pressedIcon.getIconHeight()); } return h; } /** triggers the associated action */ public void fireAction(ActionEvent e){ action.actionPerformed(e); } public String getTooltipText(){ return tooltipText; } public void setTooltipText(String tooltip){ this.tooltipText = tooltip; } /** Do not call directly as it a side effect of listening to the action changes. */ public void propertyChange(PropertyChangeEvent evt) { // track changes in the Action String prop = evt.getPropertyName(); if (prop.equals(AbstractAction.SHORT_DESCRIPTION)){ setTooltipText((String)evt.getNewValue()); } else if (prop.equals(AbstractAction.SMALL_ICON)){ setIcon((Icon) evt.getNewValue()); } else if (prop.equals("enabled")){ setEnabled(((Boolean)evt.getNewValue()).booleanValue()); } } } vldocking_2.1.4/src/com/vlsolutions/swing/tabbedpane/package.html0000644000175000017500000000071510573516344025174 0ustar twernertwerner The extended TabbedPane component for VLDocking.

This package contains classes allowing to embed buttons into the tabs of a jtabbedpane.

Although it supports any number of tabs, the current implementation for the docking framework only uses one : a close rollover button located on the right of the tab's label. vldocking_2.1.4/src/com/vlsolutions/swing/toolbars/0000755000175000017500000000000010573516350022445 5ustar twernertwernervldocking_2.1.4/src/com/vlsolutions/swing/toolbars/doc-files/0000755000175000017500000000000010573516344024315 5ustar twernertwernervldocking_2.1.4/src/com/vlsolutions/swing/toolbars/doc-files/overview.gif0000644000175000017500000001124010573516344026650 0ustar twernertwernerGIF89a,!!))111BBBJ!JJRRZ)c1cckBkksJss{RcƄkƌsΔ֥֭޵Ƶ!!))11BBJJRRcckk焄猌甔便ﭭﵵ!P,,H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիX"$ׯ`ÊKٳhӪ]˶۷pʝKEZݛE) LÈ+^̸ǐ#KL˘3S"`CWM.P^ͺװc˞M6s뎍{oآLsjLeIF*sSVnTӸ_>9w=WŐCr iQ0G;te''mWG$`G0 bWzT@ PA =pp"@(mD L7T;@ .HC)q > )q >D8ux@}%@G9HZREDEf@5М9Еe(P'& B0n/ ET<`iHqN%(E B )  ڪCi) F`5p@G6@%(BcdBmn_&qY/h ѫ+ RR j FBMG`) C~"1Ă qP4I0 vKhD2{\G"B@`k/' @e:%h PH LD~䤏4FPe CAeQ& zWaiQd+P @iH LAk5IC%> ;uYl˾ۨCB vKpgxCG@T}tZ NPWւC@^حI1i52n?pT2@B!+Ҽ@n]zWU/ d hTM|I1 (ֱ00ؚ`q~ SB.U ! B" rPrLrI{XD5U"| 9B¦̪ZȮz FZձT@ 9ZC 31ka$ySDp*Td"H !ZɌ5CRI *Wްr7N# XX1eC^2%d`4CbL2fJf84y̦6nz 8IrL:vt5  PRGzNgG9JI(GK"DQF*LB?F(JD )N@Ţ"MMHjx*iK`v2Ip .r: jHMnBMQ?bҭTP*S[zӨZU$HQ5իz!]mV3֯ e(UzֶZ$ iAլvuX1׻^kA%aX$B},4RZֱSE${٘r|jg/ٵ.uBi5Ԣv5k; Uvllي[ֶak ׯ-jpRv=s ~u5u[VwVŮX ^v-W[Q7U{߫U }O:%e_ x*-\XmNXK8/| +v~ tēݬ Fxn1u_ 8?Q7/ }D(A&Y/K.{eOyUjy˷K143ќ.l^gjΙuƲkϫk̺έ\dטuh^ ;'nAl./6]hdԞ ld鶷_n{33nKcnSʭZy[7Jo| M /Q\ oxK'/ьw7w{|ލ1r|x sd˜ήo.eJNsӄF ғ3DWӇK}G˱nCx\NdӮmbw;^tDg.]W ov|!nXߩA,XAyO<_o=H>/{s=Ih=ѧMi_B}Qs~_'~ѥk_)>ߓI?/ߟ\~gj~vv Hke7oVmf#$l&⇂.s0} 84'}8ǂ2؃ց%(>1ȃF8g۷QSHUWDjKlMnh[k]:J؅YhkmȀoX=HA((pNa6i(x%+戸fK@`8 %@"m8,pPP@@2Px=P%txPЋ88PH؈_ol8PNpPЊaQ"Pȇ@NHHш8؉8pOx2|(= ؑ!q2 H((`h. 2hO" &hؑ* kaP""(pKpQin5I6Y5=PjiZ2kYX_ѓȐ, bi|)|yxɏ،@d ZDZCqHJ?ѤNP;1TVz7ZZ\ڥ3`b:/Qfh+ln~rqZ$qx*z ѧ~ʠ.Ix%aQ:ZzrѨک<:B1P01!+BcjJP a P+` Iګ:q@ @<'֊*J`Ppʪ<'` pI0Jj*J$Bhѭ7!`B PpJ@! $0PzI 5k(,@J;A `PP0I PUڃ&*1@@ JתJ5[C1Uk 1p?[KXpʶB񭕫1 xaZz[jl+nExo ۶g+kh뻾'ۺj*Zd{G- 2K*I*ʺ<@@ݛ1 B஘kjZު8XP` j$мlJ*̪[K+ ˸;+).0K;vldocking_2.1.4/src/com/vlsolutions/swing/toolbars/BackgroundPainter.java0000644000175000017500000000056210573516344026720 0ustar twernertwernerpackage com.vlsolutions.swing.toolbars; import java.awt.Graphics; import javax.swing.JComponent; /** An interface implemented by objects which can paint toolbar backgrounds. * * * @author Lilian Chamontin, VLSolutions * @since 2.1.4 */ public interface BackgroundPainter { public void paintBackground(JComponent component, Graphics g); } vldocking_2.1.4/src/com/vlsolutions/swing/toolbars/RolloverIcon.java0000644000175000017500000001263510573516350025734 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.toolbars; import java.awt.Color; import java.awt.Component; import java.awt.Graphics; import javax.swing.GrayFilter; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.UIManager; /** A custom Icon to have a nice rollover effect for toolbar icons. *

* This icon uses a gray version of the provided image and paints it under the original one. * * @author Lilian Chamontin, VLSolutions */ public class RolloverIcon implements Icon{ private int shadowWidth = 1; private int shadowHeight = 1; private Icon icon, shadowIcon; public RolloverIcon(Icon icon){ this.icon = icon; shadowIcon = new ImageIcon(GrayFilter.createDisabledImage(((ImageIcon)icon).getImage())); } public int getIconHeight(){ return icon.getIconWidth(); } public int getIconWidth(){ return icon.getIconHeight(); } public void paintIcon(Component c, Graphics g, int x, int y){ Color highlight = UIManager.getColor("controlLtHighlight"); Color shadow = UIManager.getColor("controlShadow"); g.setColor(highlight); g.fillRect(x, y, getIconWidth(), getIconHeight()); shadowIcon.paintIcon(c, g, x + shadowWidth-1, y + shadowHeight-1); icon.paintIcon(c, g, x-1, y-1); } } vldocking_2.1.4/src/com/vlsolutions/swing/toolbars/RoundedBorder.java0000644000175000017500000001172610573516350026055 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.toolbars; import java.awt.Color; import java.awt.Component; import java.awt.Graphics; import java.awt.Insets; import javax.swing.UIManager; import javax.swing.border.Border; /** A simple rounded border. * * Can be used anywhere a rounded border is needed (no specific purpose). * * @author Lilian Chamontin, VLSolutions */ public class RoundedBorder implements Border { private Insets insets = new Insets(2,2,2,2); private Color shadow = UIManager.getColor("controlShadow"); public RoundedBorder() { } public boolean isBorderOpaque() { return false; } public void paintBorder(Component component, Graphics graphics, int x, int y, int w, int h) { graphics.setColor(shadow); graphics.drawRoundRect(x,y, w-1, h-1, 9, 9); } public Insets getBorderInsets(Component component) { return insets; } } vldocking_2.1.4/src/com/vlsolutions/swing/toolbars/ToolBarButtonBorder.java0000644000175000017500000001570010573516350027207 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.toolbars; import java.awt.Color; import java.awt.Component; import java.awt.Graphics; import java.awt.Image; import java.awt.Insets; import javax.swing.AbstractButton; import javax.swing.ImageIcon; import javax.swing.UIManager; import javax.swing.border.Border; /** A border suitable for toolbar buttons. *

* Paints a nice button effect with rounded corners. * * @author Lilian Chamontin, vlsolutions. * @version 1.0 * @since 2.0 */ public class ToolBarButtonBorder implements Border { private boolean pressed; public ToolBarButtonBorder() { } private static Image borderImage = new ImageIcon(ToolBarButtonBorder.class.getResource("toolbarbuttonborder.png")).getImage(); private static Image pressedBorderImage = new ImageIcon(ToolBarButtonBorder.class.getResource("toolbarbuttonborder_pressed.png")).getImage(); static int borderWidth = borderImage.getWidth(null); static int borderHeight = borderImage.getHeight(null); private boolean paintTopLeft = true; private Insets insets = new Insets(2, 2, 2, 2); public boolean isBorderOpaque() { return false; } public void paintBorder(Component component, Graphics graphics, int x, int y, int w, int h) { Image img; if (pressed){ img = pressedBorderImage; } else { img = borderImage; } // top right corner graphics.drawImage(img, x+ w -5, y, x+w, y+5, borderWidth-5,0, borderWidth, 5, null); // vertical right graphics.drawImage(img, x+ w -5, y+5, x+w, y+h-5, borderWidth-5,5, borderWidth, borderHeight-5, null); // bottom-right corner graphics.drawImage(img, x+ w -5, y+h-5, x+w, y+h, borderWidth-5,borderHeight-5, borderWidth, borderHeight, null); // horizontal bottom graphics.drawImage(img, x+5, y+h-5, x+w-5, y+h, 5,borderHeight-5, borderWidth-5, borderHeight, null); // bottom left corner graphics.drawImage(img, x, y+h-5, x+5, y+h, 0, borderHeight-5, 5, borderHeight, null); // horizontal top graphics.drawImage(img, x+5, y, x+w-5, y+5, 5,0, borderHeight-5, 5, null); // vertical left graphics.drawImage(img, x, y+5, x+5, y+h-5, 0,5, 5, borderHeight-5, null); // top left corner graphics.drawImage(img, x, y, x+5, y+5, 0,0, 5, 5, null); } public Insets getBorderInsets(Component component) { if (component instanceof AbstractButton){ AbstractButton btn = (AbstractButton) component; Insets i = btn.getMargin(); i.top+= insets.top; i.left += insets.left; i.right += insets.right; i.bottom += insets.bottom; return i; } else { return insets; } } public boolean isPressed() { return pressed; } public void setPressed(boolean pressed) { this.pressed = pressed; } } vldocking_2.1.4/src/com/vlsolutions/swing/toolbars/ToolBarConstraints.java0000644000175000017500000001420210573516350027101 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.toolbars; /** Constraints to be used with the ToolBarLayout. *

* Depending on the orientation of the layout, the two integers majorOrder and minorOrder * express the opposite measures : *

    *
  • in an horizontal layout, majorOrder is the ROW, and minorOrder is the COLUMN *
  • in a vertical layout, majorOrder is the COLUMN, and minorOrder is the ROW *
*

* Example : To layout two toolbars horizontally on an horizontal layout, use the following constraints * (0,0) and (0,1) (the column is the minor order on an horizontal layout). *

* to layout them in a row (one above the other), use the constraints (0,0) and (1,0) (the row * is the major order on an horizontal layout). * * @author Lilian Chamontin, VLSolutions */ public class ToolBarConstraints { /** The major order is the row index for horizontal toolbars, and the column index for * vertical toolbars. */ public int majorOrder; /** The minor order is the column index for horizontal toolbars, and the row index for * vertical toolbars. */ public int minorOrder; /** Set to -1/0/+1 during drag/drop phase to allow insertion between rows/columns. * Do not use it outside drag and drop operations. */ /* package protected */ int majorOffset = 0; /** Set to -1/0-31 during drag/drop phase to allow insertion between rows/columns * Do not use it outside drag and drop operations. */ /* package protected */ int minorOffset = 0; /** Constructs a new ToolBarConstraints at (0,0) */ public ToolBarConstraints() { } /** Constructs a new ToolBarConstraints at (majorOrder,minorOrder). *

* the majorOrder is the ROW for an horizontal layout, and the columns for a vertical layout. */ public ToolBarConstraints(int majorOrder, int minorOrder) { this.majorOrder = majorOrder; this.minorOrder = minorOrder; } /** Returns a description of these constraints. */ public String toString(){ return "ToolBarConstraints[" + majorOrder + ", " + minorOrder + "]"; } } vldocking_2.1.4/src/com/vlsolutions/swing/toolbars/ToolBarContainer.java0000644000175000017500000002550010573516350026517 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.toolbars; import java.awt.BorderLayout; import java.awt.Component; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.HashMap; import java.util.Collections; import javax.swing.JPanel; import javax.swing.SwingConstants; import javax.swing.UIManager; import java.awt.FlowLayout; /** The container for toolbar panels. *

* The layout used is BorderLayout and the CENTER component is dedicated to the user * (the other 4 places (NORTH, EAST, WEST and SOUTH are used to display the toolbar panels)). * *


* The ToolBarContainer is a JPanel with a BorderLayout, containing a user component and a maximum of four * ToolBarPanels. *

* *

* Loading and saving toolbar configurations is done with the {@link ToolBarIO} utility class, and works if * VLToolbars are registered (given a name and made know to their container by {@link #registerToolBar(VLToolBar)} ). * * @author Lilian Chamontin, VLSolutions * @update 2006/09/09 Support for LTR/RTL orientation */ public class ToolBarContainer extends JPanel { private Map componentsByContraints = new HashMap(); // this is private in borderlayout, so we need to keep a copy here private Map contraintsByComponents = new HashMap(); private Map toolBarsByName = new HashMap(); public ToolBarContainer() { setLayout(new BorderLayout()); } /** Registers a new ToolBar. *

* Registering is used when reading a xml configuration */ public void registerToolBar(VLToolBar toolbar){ if (toolbar.getName() == null){ throw new IllegalArgumentException("This toolbar hasn't got a name : cannot be registered"); } toolBarsByName.put(toolbar.getName(), toolbar); } /** Unregisters a ToolBar. *

* Registering is used when reading a xml configuration */ public void unregisterToolBar(VLToolBar toolbar){ if (toolbar.getName() == null){ return; } toolBarsByName.remove(toolbar.getName()); } /** Returns the registered toolbar associated with the given name, or null if not found */ public VLToolBar getToolBarByName(String name){ return (VLToolBar)toolBarsByName.get(name); } /** Returns the list of currently registered toolbars. * *

(eturns a new list at each invocation.) */ public List getRegisteredToolBars() { return new ArrayList(toolBarsByName.values()); } /** Overriden to track component constraints */ public void add(Component comp, Object constraints){ super.add(comp, constraints); componentsByContraints.put(constraints, comp); contraintsByComponents.put(comp, constraints); if (comp instanceof ToolBarPanel){ ToolBarPanel panel = (ToolBarPanel) comp; if (constraints.equals(BorderLayout.EAST) || constraints.equals(BorderLayout.WEST)){ panel.setOrientation(SwingConstants.VERTICAL); } // install the UI border if (constraints.equals(BorderLayout.NORTH)){ panel.setBorder(UIManager.getBorder("ToolBarPanel.topBorder")); } else if (constraints.equals(BorderLayout.WEST)){ panel.setBorder(UIManager.getBorder("ToolBarPanel.leftBorder")); } else if (constraints.equals(BorderLayout.EAST)){ panel.setBorder(UIManager.getBorder("ToolBarPanel.rightBorder")); } else if (constraints.equals(BorderLayout.SOUTH)){ panel.setBorder(UIManager.getBorder("ToolBarPanel.bottomBorder")); } } } /** Overriden to keep track of component constraints */ public void remove(Component comp){ super.remove(comp); Object constraints = contraintsByComponents.remove(comp); componentsByContraints.remove(constraints); } /** Overriden to keep track of component constraints */ public void remove(int index){ Component comp = getComponent(index); super.remove(index); Object constraints = contraintsByComponents.remove(comp); componentsByContraints.remove(constraints); } /** Overriden to keep track of component constraints */ public void removeAll(){ super.removeAll(); componentsByContraints.clear(); contraintsByComponents.clear(); } /** Returns the component for a given BorderLayout constraints */ public Component getComponentAt(Object constraints){ return (Component)componentsByContraints.get(constraints); } /** Returns the ToolBarPanel for a given BorderLayout constraints */ public ToolBarPanel getToolBarPanelAt(Object constraints){ return (ToolBarPanel) getComponentAt(constraints); } /** Returns the BorderLayout constraints of the given component */ public Object getConstraints(Component comp){ return contraintsByComponents.get(comp); } /** Creates a default ToolBarContainer with preinstalled toolbar panels on the borders with * the LEADING alignment. *

* The toolbarPanels are then accessible with getToolBarPanelAt(constraints) where constraints values * are BorderLayout.NORTH, EAST, WEST and SOUTH. */ public static ToolBarContainer createDefaultContainer(boolean topToolbar, boolean leftToolBar, boolean bottomToolBar, boolean rightToolBar){ return createDefaultContainer(topToolbar, leftToolBar, bottomToolBar, rightToolBar, FlowLayout.LEADING); } /** Creates a default ToolBarContainer with preinstalled toolbar panels on the borders with * the specified alignment * The value of the alignment argument must be one of * FlowLayout.LEFT, FlowLayout.RIGHT, * FlowLayout.CENTER, FlowLayout.LEADING, or * FlowLayout.TRAILING. *

* The toolbarPanels are then accessible with getToolBarPanelAt(constraints) where constraints values * are BorderLayout.NORTH, EAST, WEST and SOUTH. * *@author KDMurthy, Marathon Project. */ public static ToolBarContainer createDefaultContainer(boolean topToolbar, boolean leftToolBar, boolean bottomToolBar, boolean rightToolBar, int alignment){ ToolBarContainer container = new ToolBarContainer(); if (topToolbar){ ToolBarPanel panel = new ToolBarPanel(alignment); panel.setVisible(false); container.add(panel, BorderLayout.NORTH); } if (leftToolBar){ ToolBarPanel panel = new ToolBarPanel(alignment); panel.setVisible(false); container.add(panel, BorderLayout.WEST); } if (bottomToolBar){ ToolBarPanel panel = new ToolBarPanel(alignment); panel.setVisible(false); container.add(panel, BorderLayout.SOUTH); } if (rightToolBar){ ToolBarPanel panel = new ToolBarPanel(alignment); panel.setVisible(false); container.add(panel, BorderLayout.EAST); } return container; } } vldocking_2.1.4/src/com/vlsolutions/swing/toolbars/ToolBarGripper.java0000644000175000017500000001376610573516350026220 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.toolbars; import javax.swing.JComponent; import javax.swing.SwingConstants; import javax.swing.UIManager; /** The component used to have a "grip" action on a toolbar (Drag and Drop support) * * @author Lilian Chamontin, VLSolutions * @since 2.0 */ public class ToolBarGripper extends JComponent { private static final String uiClassID = "ToolBarGripperUI"; /** Id for the orientation property */ public static final String PROPERTY_ORIENTATION = "ORIENTATION"; private int orientation = SwingConstants.HORIZONTAL; private boolean collapsible = true; private boolean collapsed = false; public ToolBarGripper() { this(SwingConstants.HORIZONTAL); } public ToolBarGripper(int orientation) { setOrientation(orientation); updateUI(); } public void setOrientation(int orientation){ int old = this.orientation; this.orientation = orientation; firePropertyChange(PROPERTY_ORIENTATION, old, orientation); // not used by the framwork, but might be usefull for someone } /** Returns the orientation of this gripper (SwingConstants.HORIZONTAL/VERTICAL) */ public int getOrientation(){ return this.orientation; } /** * Resets the UI property to a value from the current look and feel. * * @see JComponent#updateUI */ public void updateUI() { setUI(UIManager.getUI(this)); } /** {@inheritDoc} * @since 2.0 */ public String getUIClassID() { return uiClassID; } /** Return true is this toolbar can be collapsed (default is true)*/ public boolean isCollapsible() { return collapsible; } public void setCollapsible(boolean collapsible) { this.collapsible = collapsible; } /** Return true is this toolbar is currently collapsed */ public boolean isCollapsed() { return collapsed; } public void setCollapsed(boolean collapsed) { this.collapsed = collapsed; } } vldocking_2.1.4/src/com/vlsolutions/swing/toolbars/ToolBarGripperUI.java0000644000175000017500000001500310573516350026440 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.toolbars; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Image; import java.awt.Insets; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import javax.swing.ImageIcon; import javax.swing.JComponent; import javax.swing.SwingConstants; import javax.swing.plaf.ComponentUI; /** The default UI for the toolbar gripper. * * @author Lilian Chamontin, VLSolutions */ public class ToolBarGripperUI extends ComponentUI{ /** the "grip" (an alpha blended dot image, 3*3 pixels, hightlighted underneath ) */ protected static Image gripImage = new ImageIcon(ToolBarGripperUI.class.getResource("gripper.png")).getImage(); protected static Image gripExpandHImage = new ImageIcon(ToolBarGripperUI.class.getResource("grip_expand_h.png")).getImage(); protected static Image gripExpandVImage = new ImageIcon(ToolBarGripperUI.class.getResource("grip_expand_v.png")).getImage(); /** Constructs a new gripper UI */ public ToolBarGripperUI() { } public static ComponentUI createUI(JComponent c) { return new ToolBarGripperUI(); } /** installs the UI and sets the preferred size of the gripper */ public void installUI(JComponent comp){ super.installUI(comp); comp.setPreferredSize(new Dimension(4,4)); } /** Paints gripper dots */ public void paint(Graphics g, JComponent comp){ ToolBarGripper gripper = (ToolBarGripper)comp; Insets insets = gripper.getInsets(); if (gripper.getOrientation() == SwingConstants.HORIZONTAL){ int dots = (gripper.getHeight())/4 -1; int dotsSize = dots * 4; int top = insets.top + gripper.getHeight()/2 - dotsSize/2; int centerX = insets.left + (gripper.getWidth() - insets.left - insets.right) / 2; for (int i=0; i < dots; i++){ g.drawImage(gripImage, centerX-1 , top+ i*4+1, null); } if (gripper.isCollapsed()){ int centerY = gripper.getHeight()/2; g.drawImage(gripExpandHImage, 0, centerY - 4, null); } } else { int dots = (gripper.getWidth())/4-1; for (int i=0; i < dots; i++){ g.drawImage(gripImage, insets.left+ i*4+2,insets.top, null); } if (gripper.isCollapsed()){ int centerX = gripper.getWidth() / 2; g.drawImage(gripExpandVImage, centerX - 4, 0, null); } } super.paint(g, comp); } } vldocking_2.1.4/src/com/vlsolutions/swing/toolbars/ToolBarIO.java0000644000175000017500000003015110573516350025102 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.toolbars; import com.vlsolutions.swing.docking.AutoHideButton; import com.vlsolutions.swing.docking.AutoHideButtonPanel; import com.vlsolutions.swing.docking.Dockable; import com.vlsolutions.swing.docking.DockableState; import com.vlsolutions.swing.docking.RelativeDockablePosition; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Container; import java.util.Collection; import java.util.Map; import java.util.HashMap; import java.util.Set; import java.util.HashSet; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import org.xml.sax.SAXNotRecognizedException; /** A utility class used to save and restore toolbars to/from an XML configuration. * * @author Lilian Chamontin, VLSolutions */ public class ToolBarIO { /** The main container */ private ToolBarContainer container; /** Constructs a new ToolBarIO utility based on the given container */ public ToolBarIO(ToolBarContainer container) { this.container = container; } /** Saves the current toolbar configuration into an XML stream. *

* The stream is not closed at the end of the operation. * * @see #readXML(InputStream) * */ public void writeXML(OutputStream stream) throws IOException { PrintWriter out = new PrintWriter(stream); out.println(""); out.println(""); xmlWriteContainer(out); out.println(""); out.flush(); } private void xmlWriteContainer(PrintWriter out){ out.println(""); Component [] comps = container.getComponents(); for (int i=0; i < comps.length; i++){ Object constraints = container.getConstraints(comps[i]); if (constraints.equals(BorderLayout.NORTH)){ ToolBarPanel panel = container.getToolBarPanelAt(constraints); xmlWriteToolBarPanel(out, panel, "top"); } else if (constraints.equals(BorderLayout.WEST)){ ToolBarPanel panel = container.getToolBarPanelAt(constraints); xmlWriteToolBarPanel(out, panel, "left"); } else if (constraints.equals(BorderLayout.SOUTH)){ ToolBarPanel panel = container.getToolBarPanelAt(constraints); xmlWriteToolBarPanel(out, panel, "bottom"); } else if (constraints.equals(BorderLayout.EAST)){ ToolBarPanel panel = container.getToolBarPanelAt(constraints); xmlWriteToolBarPanel(out, panel, "right"); } } out.println(""); } private void xmlWriteToolBarPanel(PrintWriter out, ToolBarPanel panel, String position){ out.println(""); ToolBarPanelLayout layout = (ToolBarPanelLayout) panel.getLayout(); Component [] children = layout.getComponents(); // toolbars only for (int i=0; i < children.length; i++){ VLToolBar tb = (VLToolBar) children[i]; ToolBarConstraints tc = layout.getConstraints(tb); out.println(""); } out.println(""); } /** Reads an XML encoded stream as the toolbar configuration. *

* When the method returns, the container is totally reconfigured with possibly different * toolbars at different positions. *

* Note : The VLToolBars of the stream must be registered with * the {@link ToolBarContainer#registerToolBar(VLToolBar) registerToolBar} method, * prior readXML. *

Also note that the container must already contain its ToolBarPanels before reading * the configuration. * *

* Dismisses all visible toolbars. *

* The stream is not closed at the end of the operation. * @see #writeXML(OutputStream) * @see ToolBarContainer#registerToolBar(VLToolBar) * @return a descriptor of the reading operation(useful for example to know the registered toolbars, that weren't * loaded (missing) from the input file). * */ public ToolBarIOReadInfo readXML(InputStream in) throws ParserConfigurationException, IOException, SAXException { ToolBarIOReadInfo tri = new ToolBarIOReadInfo(); // first clear the toolbar panels Component [] comps = container.getComponents(); for (int i=0; i < comps.length; i++){ Object constraints = container.getConstraints(comps[i]); if (constraints.equals(BorderLayout.NORTH)){ ((Container)comps[i]).removeAll(); } else if (constraints.equals(BorderLayout.WEST)){ ((Container)comps[i]).removeAll(); } else if (constraints.equals(BorderLayout.SOUTH)){ ((Container)comps[i]).removeAll(); } else if (constraints.equals(BorderLayout.EAST)){ ((Container)comps[i]).removeAll(); } } DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document doc = builder.parse(in); Element root = doc.getDocumentElement(); NodeList children = root.getChildNodes(); for (int i = 0, len = children.getLength(); i < len; i++) { Node child = children.item(i); xmlReadRootNode(child, tri); } tri.setRegisteredToolbars(container.getRegisteredToolBars()); tri.finishLoading(); container.revalidate(); return tri; } private void xmlReadRootNode(Node node, ToolBarIOReadInfo tri) throws SAXException{ if (node.getNodeType() == Node.ELEMENT_NODE){ Element elt = (Element) node; String name = elt.getNodeName(); if (name.equals("Container")){ NodeList children = node.getChildNodes(); for (int i = 0, len = children.getLength(); i < len; i++) { Node child = children.item(i); xmlReadContainerNode(child, tri); } } else { throw new SAXNotRecognizedException(name); } } } private void xmlReadContainerNode(Node node, ToolBarIOReadInfo tri) throws SAXException{ if (node.getNodeType() == Node.ELEMENT_NODE){ Element elt = (Element) node; String name = elt.getNodeName(); if (name.equals("ToolBarPanel")){ String position = elt.getAttribute("position"); ToolBarPanel tp = null; if (position.equals("top")){ tp = container.getToolBarPanelAt(BorderLayout.NORTH); } else if (position.equals("left")){ tp = container.getToolBarPanelAt(BorderLayout.WEST); } else if (position.equals("bottom")){ tp = container.getToolBarPanelAt(BorderLayout.SOUTH); } else if (position.equals("right")){ tp = container.getToolBarPanelAt(BorderLayout.EAST); } NodeList children = elt.getElementsByTagName("ToolBar"); for (int i = 0, len = children.getLength(); i < len; i++) { xmlReadToolBarPanelNode(tp, (Element)children.item(i), tri); } tp.revalidate(); } else { throw new SAXNotRecognizedException(name); } } } private void xmlReadToolBarPanelNode(ToolBarPanel panel, Element toolbarElt, ToolBarIOReadInfo tri) { String toolbarName = toolbarElt.getAttribute("name"); int major = Integer.parseInt(toolbarElt.getAttribute("major")); int minor = Integer.parseInt(toolbarElt.getAttribute("minor")); boolean collapsed = Boolean.valueOf(toolbarElt.getAttribute("collapsed")).booleanValue(); //2.0.6b ToolBarConstraints tc = new ToolBarConstraints(major, minor); VLToolBar tb = container.getToolBarByName(toolbarName); if (tb != null) { tb.setCollapsed(collapsed); // 2.0.6b panel.add(tb, tc); tri.notifyToolbarInstalled(tb); } else { // If the ToolBar is not registered ignore it tri.notifyUnknownToolbarFound(toolbarName); } } } vldocking_2.1.4/src/com/vlsolutions/swing/toolbars/ToolBarIOReadInfo.java0000644000175000017500000000332010573516344026513 0ustar twernertwernerpackage com.vlsolutions.swing.toolbars; import java.util.ArrayList; import java.util.Collection; import java.util.List; /** Descriptor of the loading operation of toolbars. * *

returns useful informations such as the toolbars registered and successfully loaded, and * the ones not loaded. * * @author Lilian Chamontin, VLSolutions */ public class ToolBarIOReadInfo { List notInstalledToolBarList; List installedToolBarList = new ArrayList(); List unknownToolBarNames = new ArrayList(); List registeredToolbars; public ToolBarIOReadInfo() { } /** returns the list of toolbars that were successfully loaded from the toolbarIO operation */ public List getInstalledToolbars(){ return installedToolBarList; } /** returns the list of toolbars that weren't loaded from the stream (but registered) */ public List getNotInstalledToolbars(){ return notInstalledToolBarList; } /** Return the list of toolbars names (String) found in the stream but not registered * (these toolbars cannot be loaded, so the API can only report their name). */ public List getUnknownToolbarNames(){ return unknownToolBarNames; } void notifyToolbarInstalled(VLToolBar tb){ installedToolBarList.add(tb); } void setRegisteredToolbars(List registered) { this.registeredToolbars = registered; } /** invoked on completion of loading */ void finishLoading(){ this.notInstalledToolBarList = new ArrayList(registeredToolbars); notInstalledToolBarList.removeAll(installedToolBarList); } void notifyUnknownToolbarFound(String toolbarName) { unknownToolBarNames.add(toolbarName); } } vldocking_2.1.4/src/com/vlsolutions/swing/toolbars/ToolBarPanel.java0000644000175000017500000002306110573516350025634 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.toolbars; import java.awt.Component; import java.awt.FlowLayout; import java.awt.Graphics; import java.util.ArrayList; import javax.swing.JButton; import javax.swing.JPanel; import javax.swing.JToolBar; import javax.swing.JToolBar.Separator; import javax.swing.SwingConstants; /** The toolbar panel is able to receive multiple toolbars and arrange them in * many columns or rows (depending on the horizontal/vertical orientation). * *


* The ToolBarPanel is a JPanel with a ToolBarPanelLayout. It support horizontal and vertical orientation, * and can contain one or more VLToolbars (with given ToolBarContraints for positionning). *

* @author Lilian Chamontin, VLSolutions * @update 2006/09/09 Support for LTR and RTL component orientation */ public class ToolBarPanel extends JPanel { private int orientation = SwingConstants.HORIZONTAL; /** an optionnal background painter */ private BackgroundPainter painter; /** * Constructs a new toobar panel with a LEADING alignment. */ public ToolBarPanel() { this(FlowLayout.LEADING); } /** * Constructs a new ToolBarPanel with the specified * alignment. * @param align the alignment value * The value of the alignment argument must be one of * FlowLayout.LEFT, FlowLayout.RIGHT, * FlowLayout.CENTER, FlowLayout.LEADING, or * FlowLayout.TRAILING. * */ public ToolBarPanel(int align) { this(align, null); } /** * Constructs a new ToolBarPanel with the specified * alignment and background painter. * @param align the alignment value * The value of the alignment argument must be one of * FlowLayout.LEFT, FlowLayout.RIGHT, * FlowLayout.CENTER, FlowLayout.LEADING, or * FlowLayout.TRAILING. * @param painter the background painter. * @since 2.1.4 */ public ToolBarPanel(int align, BackgroundPainter painter) { setLayout(new ToolBarPanelLayout(this, align)); this.painter = painter; } /** Adds a new toolbar respecting the given positionning constraints. */ public void add(JToolBar toolbar){ add(toolbar, 0); setVisible(true); } /** Adds a new JToolBar to the Panel at the given row. Multiple VLToolBars * are constructed using Separators in the original JToolBar */ public void add(JToolBar toolbar, int major){ toolbar.setOrientation(orientation); VLToolBar[] bars = getVLToolBarsFromJToolBar(toolbar); for (int i = 0; i < bars.length; i++) { ToolBarConstraints toolBarConstraints = new ToolBarConstraints(major, i); add(bars[i], toolBarConstraints) ; } } /** * Helper function to convert a JToolBar into multiple VLToolBar objects. The JToolBar * is split at the separator boundary to create VLToolbars * @param bar, the JToolBar object * @return array of VLToolBar objects */ private VLToolBar[] getVLToolBarsFromJToolBar(JToolBar bar) { ArrayList vlBars = new ArrayList(); Component[] components = bar.getComponents(); VLToolBar current = new VLToolBar(); for (int i = 0; i < components.length; i++) { if (components[i] instanceof JButton) { JButton button = (JButton) components[i]; if (button.getIcon() != null) button.setText(null); current.add(button); } else if (components[i] instanceof Separator) { vlBars.add(current); current = new VLToolBar(); } else { System.err.println("Don't know how to handle this component " + components[i].getClass()); } } vlBars.add(current); return (VLToolBar[]) vlBars.toArray(new VLToolBar[vlBars.size()]); } /** Adds a new toolbar respecting the given positionning constraints. */ public void add(VLToolBar toolbar, ToolBarConstraints constraints){ toolbar.setOrientation(orientation); super.add(toolbar, constraints); setVisible(true); } public void remove(Component comp){ super.remove(comp); if (getComponentCount() == 0){ setVisible(false); } } /* Updates the orientation of this toolbar. Valid values are SwingConstants.HORIZONTAL and VERTICAL*/ public void setOrientation(int orientation){ if (this.orientation != orientation){ this.orientation = orientation; updateOrientation(); revalidate(); } } /** Returns the orientation of this toolbarpanel */ public int getOrientation(){ return this.orientation; } /** Propagates the orientation to the contained toolbars */ private void updateOrientation(){ for (int i=0; i < getComponentCount(); i++){ VLToolBar tb = (VLToolBar) getComponent(i); tb.setOrientation(orientation); } } /** Overriden for optional background painting */ public void paintComponent(Graphics g){ if (painter != null){ painter.paintBackground(this, g); } super.paintComponent(g); } /** Returns the optional background painter for this toolbar panel (may be null) *@since 2.1.4 */ public BackgroundPainter getBackgroundPainter() { return painter; } /** Updates the optional background painter for this toolbar panel * @param painter the new painer (may be null) * @since 2.1.4 */ public void setPainter(BackgroundPainter painter) { this.painter = painter; } } vldocking_2.1.4/src/com/vlsolutions/swing/toolbars/ToolBarPanelBorder.java0000644000175000017500000001763710573516350027006 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.toolbars; import java.awt.Color; import java.awt.Component; import java.awt.Graphics; import java.awt.Image; import java.awt.Insets; import javax.swing.ImageIcon; import javax.swing.UIManager; import javax.swing.border.Border; /** This is an optional class that can be used as a border for toolbar panels. * * @author Lilian Chamontin, VLSolutions */ public class ToolBarPanelBorder implements Border { public static final int TOP_PANEL = 0; public static final int LEFT_PANEL = 1; public static final int BOTTOM_PANEL = 2; public static final int RIGHT_PANEL = 3; private static Image borderImage = new ImageIcon(ToolBarButtonBorder.class.getResource("toolbarpanelborder.png")).getImage(); static int borderWidth = borderImage.getWidth(null); static int borderHeight = borderImage.getHeight(null); private Insets insets; private int panelPosition; public ToolBarPanelBorder() { this(TOP_PANEL); } public ToolBarPanelBorder(int panelPosition) { this.panelPosition = panelPosition; switch(panelPosition){ case TOP_PANEL: insets = new Insets(1, 1, 4, 1); break; case LEFT_PANEL: insets = new Insets(1, 1, 1, 4); break; case BOTTOM_PANEL: insets = new Insets(4, 1, 1, 1); break; case RIGHT_PANEL: insets = new Insets(1, 4, 1, 1); break; } } public boolean isBorderOpaque() { return false; } public void paintBorder(Component component, Graphics graphics, int x, int y, int w, int h) { switch (panelPosition){ case TOP_PANEL: // horizontal bottom graphics.drawImage(borderImage, x, y+h-5, x+w, y+h, 5,borderHeight-5, borderWidth-5, borderHeight, null); // bottom-right corner /* graphics.drawImage(borderImage, x+ w -SIDE, y+h-SIDE, x+w, y+h, borderWidth-SIDE,borderHeight-SIDE, borderWidth, borderWidth, null); // bottom left graphics.drawImage(borderImage, x, y+h-SIDE, x+SIDE, y+h, 0, borderHeight-SIDE, SIDE, borderHeight, null);*/ break; case LEFT_PANEL: // vertical right graphics.drawImage(borderImage, x+ w -5, y, x+w, y+h, borderWidth-5,5, borderWidth, borderHeight-5, null); break; case BOTTOM_PANEL: // horizontal top graphics.drawImage(borderImage, x, y, x+w, y+5, 5,0, borderHeight-5, 5, null); break; case RIGHT_PANEL: // vertical left graphics.drawImage(borderImage, x, y, x+5, y+h, 0,5, 5, borderHeight-5, null); break; } /* // top right corner graphics.drawImage(borderImage, x+ w -5, y, x+w, y+5, borderWidth-5,0, borderWidth, 5, null); // vertical right graphics.drawImage(borderImage, x+ w -5, y+5, x+w, y+h-5, borderWidth-5,5, borderWidth, borderHeight-5, null); // bottom-right corner graphics.drawImage(borderImage, x+ w -5, y+h-5, x+w, y+h, borderHeight-5,borderWidth-5, borderWidth, borderHeight, null); // horizontal bottom graphics.drawImage(borderImage, x+5, y+h-5, x+w-5, y+h, 5,borderHeight-5, borderWidth-5, borderHeight, null); // bottom left corner graphics.drawImage(borderImage, x, y+h-5, x+5, y+h, 0, borderHeight-5, 5, borderHeight, null); // horizontal top graphics.drawImage(borderImage, x+5, y, x+w-5, y+5, 5,0, borderHeight-5, 5, null); // vertical left graphics.drawImage(borderImage, x, y+5, x+5, y+h-5, 0,5, 5, borderHeight-5, null); // top left corner graphics.drawImage(borderImage, x, y, x+5, y+5, 0,0, 5, 5, null); */ } public Insets getBorderInsets(Component component) { return insets; } } vldocking_2.1.4/src/com/vlsolutions/swing/toolbars/ToolBarPanelLayout.java0000644000175000017500000005640610573516350027043 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.toolbars; import java.awt.Component; import java.awt.Container; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Insets; import java.awt.LayoutManager2; import java.awt.Point; import java.awt.Rectangle; import java.util.ArrayList; import java.util.Collections; import javax.swing.SwingConstants; /** The layout of a VLToolBarPanel * * @author Lilian Chamontin, VLSolutions * @update 2006/09/09 Support for LTR and RTL component orientation */ public class ToolBarPanelLayout implements LayoutManager2{ private ToolBarPanel panel; private ArrayList componentInfos = new ArrayList(); private int gap = 3; // gap in pixels between components private int align = FlowLayout.LEADING ; public ToolBarPanelLayout(ToolBarPanel panel, int align) { this.panel = panel ; this.align = align ; } public ToolBarPanelLayout(ToolBarPanel panel) { this(panel, FlowLayout.LEADING); } /** Returns the alignment of this layout (FlowLayout.LEADING, TRAILING...) */ public int getAlign() { return align; } public void setAlign(int align) { this.align = align; } private int getAlignedX(Container target) { int left = 0 ; boolean ltr = target.getComponentOrientation().isLeftToRight() ; int width = preferredLayoutSize(target).width ; switch (align) { case FlowLayout.LEFT: left += ltr ? 0 : target.getSize().width - width ; break ; case FlowLayout.CENTER: left += (target.getSize().width - width)/2 ; break ; case FlowLayout.RIGHT: left += ltr ? target.getSize().width - width : 0 ; break ; case FlowLayout.LEADING: break ; case FlowLayout.TRAILING: left += target.getSize().width - width ; break ; } return left ; } public float getLayoutAlignmentX(Container target) { return 0.5F; } public float getLayoutAlignmentY(Container target) { return 0.5F; } public void invalidateLayout(Container target) { } public Dimension maximumLayoutSize(Container target) { return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); } public void addLayoutComponent(Component comp, Object constraints) { if (constraints == null){ throw new NullPointerException(); } else { ToolBarConstraints tc = (ToolBarConstraints) constraints; componentInfos.add(new ComponentInfo(comp, tc)); reorderComponents(); } } public ToolBarConstraints getConstraints(Component comp){ for (int i=0; i < componentInfos.size(); i++){ ComponentInfo ci = (ComponentInfo) componentInfos.get(i); if (ci.comp == comp){ return ci.constraints; } } return null; } public void removeLayoutComponent(Component comp) { for (int i=0; i < componentInfos.size(); i++){ ComponentInfo ci = (ComponentInfo) componentInfos.get(i); if (ci.comp == comp){ componentInfos.remove(i); return ; } } } public void addLayoutComponent(String name, Component comp) { } public Dimension minimumLayoutSize(Container parent) { ToolBarPanel panel = (ToolBarPanel) parent; boolean isHorizontal = panel.getOrientation() == SwingConstants.HORIZONTAL; synchronized (parent.getTreeLock()) { Dimension dim = new Dimension(0, 0); int majorCount = getMajorCount(); for (int i=0; i < majorCount; i++){ Dimension minorDim = new Dimension(0,0); ArrayList minorList = getMinorComponents(i); for (int j=0; j < minorList.size(); j++){ ComponentInfo ci = (ComponentInfo) minorList.get(j); Dimension d = ci.comp.getPreferredSize(); if (ci.comp.isVisible()){ if (isHorizontal) { minorDim.width += d.width; minorDim.height = Math.max(minorDim.height, d.height); if (j > 0){ minorDim.width += gap; } } else { minorDim.width = Math.max(minorDim.width, d.width); minorDim.height += d.height; if (j > 0){ minorDim.height += gap; } } } } if (isHorizontal){ dim.width = Math.max(dim.width, minorDim.width); dim.height += minorDim.height; } else { dim.width += minorDim.width; dim.height = Math.max(dim.height, minorDim.height); } } Insets insets = parent.getInsets(); dim.width += insets.left + insets.right; dim.height += insets.top + insets.bottom; return dim; } } public Dimension preferredLayoutSize(Container parent) { return minimumLayoutSize(parent); } /** Returns and ordered array of the contained components */ public Component [] getComponents(){ Component [] comps = new Component[componentInfos.size()]; for (int i=0; i < componentInfos.size(); i++){ ComponentInfo ci = (ComponentInfo)componentInfos.get(i); comps[i] = ci.comp; } return comps; } public void layoutContainer(Container target) { ToolBarPanel panel = (ToolBarPanel) target; boolean isHorizontal = panel.getOrientation() == SwingConstants.HORIZONTAL; boolean ltr = target.getComponentOrientation().isLeftToRight(); synchronized (target.getTreeLock()) { Collections.sort(componentInfos); Insets insets = target.getInsets(); if (isHorizontal){ int top = insets.top; int majorCount = getMajorCount(); for (int i=0; i < majorCount; i++){ int left = insets.left + getAlignedX(target); int maxHeight = 0; ArrayList minorList = getMinorComponents(i); /*for (int j=0; j < minorList.size(); j++){ ComponentInfo ci = (ComponentInfo) minorList.get(j); Component comp = ci.comp; if (comp.isVisible()){ Dimension d = comp.getPreferredSize(); comp.setBounds(left, top, d.width, d.height); left += d.width + gap; maxHeight = Math.max(maxHeight, d.height); } }*/ if (ltr) { for (int j=0; j < minorList.size(); j++){ ComponentInfo ci = (ComponentInfo) minorList.get(j); Dimension d = layoutHorizMinor(ci, left, top); if (d != null) { left += d.width + gap ; maxHeight = Math.max(maxHeight, d.height); } } } else { for (int j=minorList.size()-1; j >= 0; j--){ ComponentInfo ci = (ComponentInfo) minorList.get(j); Dimension d = layoutHorizMinor(ci, left, top); if (d != null) { left += d.width + gap ; maxHeight = Math.max(maxHeight, d.height); } } } top += maxHeight; } } else { int majorCount = getMajorCount(); /*int left = insets.left; for (int i=0; i < majorCount; i++){ int top = insets.top; int maxWidth = 0; ArrayList minorList = getMinorComponents(i); for (int j=0; j < minorList.size(); j++){ ComponentInfo ci = (ComponentInfo) minorList.get(j); Component comp = ci.comp; if (comp.isVisible()){ Dimension d = comp.getPreferredSize(); comp.setBounds(left, top, d.width, d.height); top += d.height + gap; maxWidth = Math.max(maxWidth, d.width); } } left += maxWidth;*/ int left = insets.left; if (ltr) { for (int i=0; i < majorCount; i++){ int maxWidth = layoutVertMajor(insets, left, i); left += maxWidth; } } else { for (int i=majorCount-1; i >= 0; i--){ int maxWidth = layoutVertMajor(insets, left, i); left += maxWidth; } } } } } private Dimension layoutHorizMinor(ComponentInfo ci, int left, int top) { Component comp = ci.comp ; if (comp.isVisible()) { Dimension d = comp.getPreferredSize(); comp.setBounds(left, top, d.width, d.height); return d ; } return null ; } private int layoutVertMajor(Insets insets, int left, int i) { int top = insets.top; int maxWidth = 0; ArrayList minorList = getMinorComponents(i); for (int j=0; j < minorList.size(); j++){ ComponentInfo ci = (ComponentInfo) minorList.get(j); Component comp = ci.comp; if (comp.isVisible()){ Dimension d = comp.getPreferredSize(); comp.setBounds(left, top, d.width, d.height); top += d.height + gap; maxWidth = Math.max(maxWidth, d.width); } } return maxWidth; } private void reorderComponents(){ Collections.sort(componentInfos); /* Usefull state dumps : I'll let them here for some time. System.out.println("---------------------------------------------------"); System.out.println("List of components : ----BEFORE ------"); for (int i=0; i < componentInfos.size(); i++){ ComponentInfo ci = (ComponentInfo)componentInfos.get(i); System.out.println(ci.constraints + " = " + ci.comp); } //*/ // first, insert new major orders for (int i=0; i < componentInfos.size(); i++){ ComponentInfo ci = (ComponentInfo)componentInfos.get(i); if (ci.constraints.majorOffset < 0){ ci.constraints.majorOffset = 0; for (int j=i+1; j < componentInfos.size(); j++){ ComponentInfo next = (ComponentInfo)componentInfos.get(j); next.constraints.majorOrder ++; } } else if (ci.constraints.majorOffset > 0){ ci.constraints.majorOffset = 0; for (int j=i; j < componentInfos.size(); j++){ // also increase the current one ComponentInfo next = (ComponentInfo)componentInfos.get(j); next.constraints.majorOrder ++; } } } // next, insert new minor orders for (int i=0; i < componentInfos.size(); i++){ ComponentInfo ci = (ComponentInfo)componentInfos.get(i); if (ci.constraints.minorOffset < 0){ ci.constraints.minorOffset = 0; for (int j=i+1; j < componentInfos.size(); j++){ ComponentInfo next = (ComponentInfo)componentInfos.get(j); if (next.constraints.majorOrder == ci.constraints.majorOrder){ next.constraints.minorOrder ++; } } } else if (ci.constraints.minorOffset > 0){ ci.constraints.minorOffset = 0; for (int j=i; j < componentInfos.size(); j++){ // also increase the current one ComponentInfo next = (ComponentInfo)componentInfos.get(j); if (next.constraints.majorOrder == ci.constraints.majorOrder){ next.constraints.minorOrder ++; } } } } /* System.out.println("List of components : after offsets"); for (int i=0; i < componentInfos.size(); i++){ ComponentInfo ci = (ComponentInfo)componentInfos.get(i); System.out.println(ci.constraints + " = " + ci.comp); }*/ // next, let all major and minor order be consecutive int order = 0; int minorOrder = 0; int lastMajorOrder = -1; int lastMinorOrder = -1; for (int i=0; i < componentInfos.size(); i++){ ComponentInfo ci = (ComponentInfo)componentInfos.get(i); if (lastMajorOrder == -1){ lastMajorOrder = ci.constraints.majorOrder; lastMinorOrder = ci.constraints.minorOrder; } if (ci.constraints.majorOrder == lastMajorOrder){ ci.constraints.majorOrder = order; if (ci.constraints.minorOrder == lastMinorOrder){ ci.constraints.minorOrder = minorOrder; } else { minorOrder ++; lastMinorOrder = ci.constraints.minorOrder; ci.constraints.minorOrder = minorOrder; } } else { // beginning of a new major order ++; minorOrder = 0; lastMajorOrder = ci.constraints.majorOrder; lastMinorOrder = ci.constraints.minorOrder; ci.constraints.majorOrder = order; ci.constraints.minorOrder = minorOrder; } } /* System.out.println("List of components : ------AFTER ----"); for (int i=0; i < componentInfos.size(); i++){ ComponentInfo ci = (ComponentInfo)componentInfos.get(i); System.out.println(ci.constraints + " = " + ci.comp); } */ } private ToolBarConstraints getHorizontalInsertionContraintsAt(Component draggedComponent, Point p){ ToolBarConstraints tc = new ToolBarConstraints(); int majorCount = getMajorCount(); for (int i=0; i < majorCount; i++){ Rectangle bounds = getMinorBounds(i); if (p.y < bounds.y){ // insert before first tc.majorOrder = i; tc.minorOrder = 0; tc.majorOffset = -1; return tc; } else if (p.y < bounds.y + 5){ // insert before current row tc.majorOrder = i; tc.minorOrder = 0; tc.majorOffset = -1; return tc; } else if (p.y > bounds.y + bounds.height){ // insert after.. ignore (will be tested on next loop) } else if (p.y > bounds.y + bounds.height - 5){ // insert a new major as we are just below the lower part tc.majorOrder = i; tc.minorOrder = 0; tc.majorOffset = +1; return tc; } else if (p.x < bounds.x + bounds.width){ // insert inside ArrayList minorList = getMinorComponents(i); for (int j=0; j < minorList.size(); j++){ ComponentInfo ci = (ComponentInfo) minorList.get(j); Component comp = ci.comp; if (comp.isVisible()){ if (p.x < comp.getX() + comp.getWidth()){ if (comp == draggedComponent){ return null; } else if (p.x < comp.getX() + 10){ // at the beginning of the component tc.majorOrder = i; tc.minorOrder = j; tc.minorOffset = -1; return tc; } else { // on the component but not at the beginning if (j < minorList.size()-1){ ComponentInfo next = (ComponentInfo)minorList.get(j+1); if (next.comp == draggedComponent){ return null; } } tc.majorOrder = i; tc.minorOrder = j; tc.minorOffset = +1; return tc; } } } } // not possible to reach this point } else { // after last of the row ArrayList minorList = getMinorComponents(i); tc.majorOrder = i; tc.minorOrder = minorList.size(); return tc; } } // not found... so it's after the last tc.majorOrder = majorCount; tc.minorOrder = 0; return tc; } private ToolBarConstraints getVerticalInsertionContraintsAt(Component draggedComponent, Point p){ ToolBarConstraints tc = new ToolBarConstraints(); int majorCount = getMajorCount(); for (int i=0; i < majorCount; i++){ Rectangle bounds = getMinorBounds(i); if (p.x < bounds.x){ // insert before first tc.majorOrder = i; tc.minorOrder = 0; tc.majorOffset = -1; return tc; } else if (p.x < bounds.x + 3){ // insert before current row tc.majorOrder = i; tc.minorOrder = 0; tc.majorOffset = -1; return tc; } else if (p.x > bounds.x + bounds.width){ // insert after.. ignore (will be tested on next loop) } else if (p.x > bounds.x + bounds.width - 3){ // insert a new major as we are just below the lower part tc.majorOrder = i; tc.minorOrder = 0; tc.majorOffset = +1; return tc; } else if (p.y < bounds.y + bounds.height){ // insert inside ArrayList minorList = getMinorComponents(i); for (int j=0; j < minorList.size(); j++){ ComponentInfo ci = (ComponentInfo) minorList.get(j); Component comp = ci.comp; if (comp.isVisible()){ if (p.y < comp.getY() + comp.getHeight()){ if (comp == draggedComponent){ return null; } else if (p.y < comp.getY() + 10){ // at the beginning of the component tc.majorOrder = i; tc.minorOrder = j; tc.minorOffset = -1; return tc; } else { // on the component but not at the beginning if (j < minorList.size()-1){ ComponentInfo next = (ComponentInfo)minorList.get(j+1); if (next.comp == draggedComponent){ return null; } } tc.majorOrder = i; tc.minorOrder = j; tc.minorOffset = +1; return tc; } } } } // not possible to reach this point } else { // after last of the row ArrayList minorList = getMinorComponents(i); tc.majorOrder = i; tc.minorOrder = minorList.size(); return tc; } } // not found... so it's after the last tc.majorOrder = majorCount; tc.minorOrder = 0; return tc; } /** Returns a proposed TooBarContraints for a given insertion point */ public ToolBarConstraints getInsertionContraintsAt(Component draggedComponent, Point p){ boolean isHorizontal = panel.getOrientation() == SwingConstants.HORIZONTAL; if (isHorizontal){ return getHorizontalInsertionContraintsAt(draggedComponent, p); } else { // vertical return getVerticalInsertionContraintsAt(draggedComponent, p); } } private int getMajorCount(){ int max = 0; for (int i=0; i < componentInfos.size(); i++){ ComponentInfo ci = (ComponentInfo) componentInfos.get(i); ToolBarConstraints tc = ci.constraints; if (tc.majorOrder > max){ max = tc.majorOrder; } } return max+1; } private Rectangle getMinorBounds(int majorOrder){ Rectangle r = new Rectangle(); Rectangle temp = null; for (int i=0; i < componentInfos.size(); i++){ ComponentInfo ci = (ComponentInfo) componentInfos.get(i); if (ci.constraints.majorOrder == majorOrder){ temp = ci.comp.getBounds(temp); r = r.union(temp); } } return r; } private ArrayList getMinorComponents(int majorOrder){ ArrayList list = new ArrayList(); for (int i=0; i < componentInfos.size(); i++){ ComponentInfo ci = (ComponentInfo) componentInfos.get(i); if (ci.constraints.majorOrder == majorOrder){ list.add(ci); } } return list; } private class ComponentInfo implements Comparable{ Component comp; ToolBarConstraints constraints; ComponentInfo(Component comp, ToolBarConstraints constraints){ this.comp = comp; this.constraints = constraints; } private int getCompareOrder(){ int order = constraints.majorOrder * 100000 + constraints.majorOffset * 10000 + constraints.minorOrder * 100 + constraints.minorOffset; return order; } public int compareTo(Object obj) { ComponentInfo ci = (ComponentInfo) obj; return getCompareOrder() - ci.getCompareOrder(); } } } vldocking_2.1.4/src/com/vlsolutions/swing/toolbars/ToolBarPersistence.java0000644000175000017500000001722410573516350027065 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.toolbars; import java.awt.BorderLayout; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.Collection; import java.util.Iterator; import java.util.prefs.Preferences; import javax.xml.parsers.ParserConfigurationException; import org.xml.sax.SAXException; /** * This class contains methods to keep a set of toolbars persistent. *

* The class uses the preferences framework of the java runtime, and installs a * shutdown hook to save the toolbars state on application exit. *

* Warning : this class cannot be run from a sandboxed (untrusted) environment * (unsigned applet/ java web start) as it uses classes requiring a SecurityManager * (Preferences API and Runtime shutdown hook). *

* Call loadToolBarLayout() upon application startup, after registering all ToolBars. * * @author Michael Westergaard, revised by Lilian Chamontin. * * @see ToolBarIO */ public class ToolBarPersistence implements Runnable { private final static String TOOLBAR_LAYOUT = "toolbar_layout"; //$NON-NLS-1$ private ToolBarContainer container; private ToolBarIO io; private Preferences prefs; /** * Construct a new set of persistent toolbars. * * @param mainClass the main class of the application. Will be used to * generate a reasonable name for the preferences to store toolbar * configuration * @param container the toolbarcontainer to keep persistent * @throws SecurityException if this class is invoked from an untrusted environment */ public ToolBarPersistence(Object mainClass, ToolBarContainer container) { this.container = container; this.io = new ToolBarIO(container); String nodeName = mainClass.getClass().getName().replaceFirst(mainClass.getClass().getPackage().getName() + ".", ""); //$NON-NLS-1$ //$NON-NLS-2$ prefs = Preferences.userNodeForPackage(mainClass.getClass()).node(nodeName); Runtime.getRuntime().addShutdownHook(new Thread(this)); } protected void handleUnloadedToolBar(VLToolBar toolbar) { ToolBarPanel panel = container.getToolBarPanelAt(BorderLayout.NORTH); if (panel != null) panel.add(toolbar, new ToolBarConstraints()); } /** * Load the toolbar configuration. * * @throws IOException * @throws ParserConfigurationException * @throws SAXException */ public void loadToolBarLayout() throws IOException, ParserConfigurationException, SAXException { byte data[] = prefs.getByteArray(TOOLBAR_LAYOUT, null); if (data != null) { InputStream in = new ByteArrayInputStream(data); ToolBarIOReadInfo tri = io.readXML(in); Collection unloadedToolBars = tri.getNotInstalledToolbars(); in.close(); for (Iterator i = unloadedToolBars.iterator(); i.hasNext(); ) { VLToolBar toolbar = (VLToolBar) i.next(); handleUnloadedToolBar(toolbar); } } } /** * Save the toolbar configuration. *

Masks all errors. *

don't call this method directly : it is used by the shudown hook. * * @see java.lang.Runnable#run() */ public void run() { try { saveToolBarLayout(); } catch (Exception exception) { // Mask error as we are quitting anyway } } /** * Save the toolbar configuration. * * @throws IOException */ public void saveToolBarLayout() throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); io.writeXML(out); out.close(); prefs.putByteArray(TOOLBAR_LAYOUT, out.toByteArray()); } }vldocking_2.1.4/src/com/vlsolutions/swing/toolbars/VLButtonUI.java0000644000175000017500000001304010573516350025261 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.toolbars; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Insets; import javax.swing.AbstractButton; import javax.swing.JComponent; import javax.swing.UIManager; import javax.swing.border.Border; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicToggleButtonUI; /** A UI for toolbar buttons : replaces the look and feel default UI to * have a unified toolbar rendering. * * @author Lilian Chamontin, VLSolutions */ public class VLButtonUI extends BasicToggleButtonUI { private Color highlight = UIManager.getColor("controlLtHighlight"); public VLButtonUI() { } public void paint(Graphics g, JComponent comp){ AbstractButton btn = (AbstractButton) comp; boolean rollover = btn.getModel().isRollover(); boolean selected = btn.getModel().isSelected(); boolean armed = btn.getModel().isArmed(); btn.setBorderPainted(selected || rollover); if (rollover || selected){ if (armed){ g.translate(1,1); } else { Insets i = btn.getInsets(); if (! selected){ // avoid too much effects g.setColor(highlight); g.fillRect(1,1, btn.getWidth() - 2, btn.getHeight() - 2); } } } Border b = comp.getBorder(); if (b instanceof ToolBarButtonBorder){ ((ToolBarButtonBorder)b).setPressed(selected || armed); } super.paint(g, comp); } }vldocking_2.1.4/src/com/vlsolutions/swing/toolbars/VLToolBar.java0000644000175000017500000005276310573516350025131 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.toolbars; import com.vlsolutions.swing.docking.animation.AnimationEvent; import com.vlsolutions.swing.docking.animation.AnimationListener; import com.vlsolutions.swing.docking.animation.ComponentAnimator; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Dimension; import java.awt.Insets; import java.awt.Point; import java.awt.Rectangle; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import javax.swing.AbstractButton; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JPanel; import javax.swing.JSeparator; import javax.swing.JToolBar; import javax.swing.SwingConstants; import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.border.Border; /** A JToolbar suitable for drag and drop purposes. *

* To use the toolbar feature, you must follow this pattern : *

    *
  • The toolbars must be contained initially in a ToolBarPanel (which can contain multiple toolbars) *
  • The ToolBarPanel must be contained in a ToolBarContainer (which can contain as much as 4 ToolBarPanels * , one on each border). *
  • The center component of the ToolBarContainer can be the DockingDesktop, or any user component. *
* *


* The VLToolBar contains buttons and other components, and is included in a ToolBarPanel of a ToolBarContainer . *

*

* Loading and saving toolbar configurations is done with the {@link ToolBarIO} utility class. *

* Toolbars can now be collapsed (to gain space on screen). this property is disabled by default to * keep compatibility with previous releases. For a better usage of collapsing it is better to * set a tooltip text on the toolbar (it will be propagated to the gripper, which will be the only * one component visible when collapsed). * * @author Lilian Chamontin, VLSolutions * @update 2006/02/20 Lilian Chamontin : added support for collapsible toolbars * @update 2006/03/16 Lilian Chamontin : added animation effect when collapsing toolbars * @update 2006/12/01 Lilian Chamontin : added protection againt class cast when dragging */ public class VLToolBar extends JPanel{ private ToolBarGripper gripper = new ToolBarGripper(); private boolean rolloverBorderPainted = true; private boolean rolloverContentAreaFilled = false; private boolean useCustomUI = true; private int orientation = SwingConstants.HORIZONTAL; private MouseListener buttonMouseHandler = new MouseAdapter(){ public void mouseEntered(MouseEvent e){ AbstractButton btn = (AbstractButton) e.getSource(); if ((e.getModifiersEx() & MouseEvent.BUTTON1_DOWN_MASK) == 0){ if (rolloverBorderPainted){ btn.setBorderPainted(true); } if (rolloverContentAreaFilled){ btn.setContentAreaFilled(true); } } } public void mouseExited(MouseEvent e){ AbstractButton btn = (AbstractButton) e.getSource(); btn.setBorderPainted(false); } }; /** The mouse listener in charge for toolbar drag and drop */ private GripperHandler gripperListener = new GripperHandler(); /** The border used during DnD to show that the toolbar is selected */ private Border draggedBorder = new ToolBarButtonBorder(); private VLToolBarLayout horizontalLayout = new VLToolBarLayout(true, 0); private VLToolBarLayout verticalLayout = new VLToolBarLayout(false, 0); /** Constructs a toolbar with a null name (this toolbar will not be * able to write its structure in a XML encoder, unless you call setName(String) * with a non null name before saving). * ). */ public VLToolBar() { this(null); } /** Constructs a toolbar with the given name. *

* The name is used when reading/writing XML configuration. It must not be null if * you use this feature. */ public VLToolBar(String name) { setName(name); setLayout(horizontalLayout); gripper.addMouseMotionListener(gripperListener); gripper.addMouseListener(gripperListener); gripper.setPreferredSize(new Dimension(4, 20)); //gripper.setMinimumSize(new Dimension(4, 4)); add(gripper); setBorder(BorderFactory.createEmptyBorder(2,2,2,2)); gripper.setToolTipText(name); } /** Adds a new separator to this toolbar */ public void addSeparator(){ Dimension size = (Dimension)(UIManager.get("ToolBar.separatorSize")); JToolBar.Separator sep = new JToolBar.Separator(); sep.setOrientation(orientation); if (orientation == SwingConstants.HORIZONTAL){ sep.setOrientation(SwingConstants.VERTICAL); sep.setPreferredSize(size); add(sep); } else { sep.setOrientation(SwingConstants.HORIZONTAL); sep.setPreferredSize(size); add(sep); } } /** Overriden to track AbstractButton added */ public Component add(Component comp){ if (comp instanceof AbstractButton){ return add((AbstractButton) comp); } else { if (!(comp instanceof ToolBarGripper)) { comp.setVisible(!gripper.isCollapsed()); } return super.add(comp); } } /** Adds a new button to this toolbar */ public Component add(AbstractButton button){ if (useCustomUI){ installButtonUI(button); } button.setVisible(!gripper.isCollapsed()); super.add(button); configureButton(button); installMouseHandler(button); return button; } /** Adds a new button to this toolbar */ public Component add(JButton button){ // this method is here to maintain backward compatibility return add((AbstractButton) button); } /** Install custom UI for this button : a light rollover effet and a custom rounded/shaded border. *

* This method can be overriden to replace the provided "look and feel" which uses the follwing configuration : *

    *
  • install a VLButtonUI *
  • set 2 pixels margins *
  • set a ToolBarButtonBorder. *
*/ public void installButtonUI(AbstractButton button){ button.setMargin(new Insets(2,2,2,2)); button.setUI(new VLButtonUI()); button.setBorder(new ToolBarButtonBorder()); } /** Used internally to add a mouse listener to the button. *

* Can be overriden to implement custom event handling. */ public void installMouseHandler(AbstractButton button){ button.addMouseListener(buttonMouseHandler); } /** This method is invoked upon adding a button to the toolbar. It can be * overriden to provide another look or feel. *

* Default settings are : *

  • setRolloverEnabled(true) *
  • setContentAreaFilled(false); *
  • setOpaque(false) *
  • setBorderPainted(false) *
*/ public void configureButton(AbstractButton button){ button.setRolloverEnabled(true); button.setContentAreaFilled(false); button.setOpaque(false); button.setBorderPainted(false); } /** Updates the rolloverBorderPainted property. *

* If true, when one of the toolbar buttons is rolled-over, its border will be shown. *

* DefaultValue is true */ public void setRolloverBorderPainted(boolean painted){ this.rolloverBorderPainted = painted; } /** Returns the state of the rolloverBorderPainted property */ public boolean isRolloverBorderPainter(){ return rolloverBorderPainted; } /** Updates the rolloverContentAreaFilled property. *

* If true, when one of the toolbar buttons is rolled-over, its content will be filled. *

* Default value is false to accomodate with VLButtonUI which paints itself the button * interiors. * */ public void setRolloverContentAreaFilled(boolean filled){ this.rolloverContentAreaFilled = filled; } /** Returns the value of the rolloverContentAreaFilled property */ public boolean isRolloverContentAreaFilled(){ return rolloverContentAreaFilled; } /** Updates the useCustomUI property. *

* Default value is true. *

* When set to true the installButtonUI() method will be called when a button is added to this * toolbar. */ public void setUseCustomUI(boolean useCustomUI){ this.useCustomUI = useCustomUI; } /** Return the value of the useCustomUI property */ public boolean isUseCustomUI(){ return useCustomUI; } /** Changes the border used during drag and drop of the toolbar. *

* For a better user experience, please note to install an empty border of the * same Insets than this one (otherwise, there will be a size change of the toolbar at the beginning * of the drag and after the drop). */ public void setDraggedBorder(Border border){ this.draggedBorder = border; } /** Returns the border used during drag and drop or the toolbar */ public Border getDraggedBorder(){ return this.draggedBorder; } private void gripperDragged(MouseEvent e){ // where are we ? Component gripper = e.getComponent(); ToolBarPanel panel = (ToolBarPanel) this.getParent(); if (!(panel.getParent() instanceof ToolBarContainer)){ //2006/12/01 // this is a safety for users willing to include toolbar panels outside // a toolbar container (in that case, these toolbars aren't draggable). return; } ToolBarContainer container = (ToolBarContainer) panel.getParent(); Point tbPanelPoint = SwingUtilities.convertPoint(e.getComponent(), e.getPoint(), panel); if (panel.contains(tbPanelPoint)){ // we're dragging inside the same ToolbarPanel ToolBarPanelLayout layout = (ToolBarPanelLayout) panel.getLayout(); ToolBarConstraints constraints = layout.getInsertionContraintsAt(this, tbPanelPoint); if (constraints != null){ panel.remove(this); panel.add(this, constraints); panel.revalidate(); } } else { // we're outside this toolbar panel, check if we're above another toolbar // or near an empty one Rectangle containerBounds = container.getBounds(); Rectangle invisiblePanelBounds = new Rectangle(containerBounds); ToolBarPanel topPanel = (ToolBarPanel)container.getComponentAt(BorderLayout.NORTH); invisiblePanelBounds.height = 10; if (checkGripperOnOtherPanel(topPanel, e, invisiblePanelBounds)){ return; } invisiblePanelBounds.y = containerBounds.y + containerBounds.height - 10; ToolBarPanel bottomPanel = (ToolBarPanel)container.getComponentAt(BorderLayout.SOUTH); if (checkGripperOnOtherPanel(bottomPanel, e, invisiblePanelBounds)){ return; } invisiblePanelBounds.y = containerBounds.y; invisiblePanelBounds.height = containerBounds.height; invisiblePanelBounds.width = 10; ToolBarPanel leftPanel = (ToolBarPanel)container.getComponentAt(BorderLayout.WEST); if (checkGripperOnOtherPanel(leftPanel, e, invisiblePanelBounds)){ return; } invisiblePanelBounds.x = containerBounds.x + containerBounds.width - 10; ToolBarPanel rightPanel = (ToolBarPanel)container.getComponentAt(BorderLayout.EAST); if (checkGripperOnOtherPanel(rightPanel, e, invisiblePanelBounds)){ return; } } } private boolean checkGripperOnOtherPanel(ToolBarPanel panel, MouseEvent e, Rectangle invisibleBounds){ if (panel != null && panel != getParent()){ if(panel.isVisible()){ Point panelPoint = SwingUtilities.convertPoint(this, e.getPoint(), panel); if (panel.contains(panelPoint)){ gripperDraggedOnOtherVisiblePanel(panel, panelPoint); return true; } } else { // not visible Point containerPoint = SwingUtilities.convertPoint(this, e.getPoint(), panel.getParent()); if (invisibleBounds.contains(containerPoint)){ ToolBarPanel parent = (ToolBarPanel)getParent(); parent.remove(this); panel.add(this, new ToolBarConstraints(0,0)); // the panel is not visible == empty panel.revalidate(); if (parent.getComponentCount() == 0){ parent.setVisible(false); // last toolbar : hideit } return true; } } } return false; } private void gripperDraggedOnOtherVisiblePanel(ToolBarPanel panel, Point point){ // we're dragging inside another ToolbarPanel ToolBarPanelLayout layout = (ToolBarPanelLayout) panel.getLayout(); ToolBarConstraints constraints = layout.getInsertionContraintsAt(this, point); if (constraints != null){ ToolBarPanel parent = (ToolBarPanel)getParent(); parent.remove(this); panel.add(this, constraints); panel.revalidate(); } } public String toString(){ return "VLToolBar " + getName(); } /** Updates the orientation of this toolbar. *

* This method is called directly by the framework on toolbar installation or * during drag and drop. */ public void setOrientation(int orientation){ if (this.orientation != orientation){ this.orientation = orientation; gripper.setOrientation(orientation); Component [] comps = getComponents(); removeAll(); if (orientation == SwingConstants.HORIZONTAL){ gripper.setPreferredSize(new Dimension(4, 20)); setLayout(horizontalLayout); for (int i=0; i < comps.length; i++){ if (comps[i] instanceof JToolBar.Separator){ JToolBar.Separator sep = (JToolBar.Separator) comps[i]; sep.setOrientation(SwingConstants.VERTICAL); } add(comps[i]); } } else { gripper.setPreferredSize(new Dimension(20,4)); setLayout(verticalLayout); // gripper.setIcon(vGripIcon); for (int i=0; i < comps.length; i++){ if (comps[i] instanceof JSeparator){ JSeparator sep = (JSeparator) comps[i]; sep.setOrientation(SwingConstants.HORIZONTAL); } add(comps[i]); } } revalidate(); } } /** Updates the tooltip of the toolbar, and propagates it to the toolbar gripper. */ public void setToolTipText(String tooltip){ super.setToolTipText(tooltip); gripper.setToolTipText(tooltip); } boolean isInAnimationCycle = false; private void gripperClicked(MouseEvent e){ if (isCollapsible() && ! isInAnimationCycle){ setCollapsed(!gripper.isCollapsed()); } } /** Hides the toolbar (just showing the gripper) */ public void setCollapsed(final boolean collapsed) { if (collapsed){ // added a subtle animation effect to give more polish to the collapsing //2006/03/16 Rectangle bounds = getBounds(); Rectangle newBounds; float animSpeed ; if (orientation == SwingConstants.HORIZONTAL){ newBounds = new Rectangle(bounds.x,bounds.y, 20, getHeight()); animSpeed = getWidth() / 800f; // pix / sec } else { newBounds = new Rectangle(bounds.x,bounds.y, getWidth(), 20); animSpeed = getHeight()/ 800f; // pix / sec } ComponentAnimator canim = new ComponentAnimator(this, bounds, newBounds, animSpeed); canim.addAnimationListener(new AnimationListener() { public void animation(AnimationEvent e) { if (e.getState() == AnimationEvent.ANIMATION_END){ gripperListener.resetBorder(); finishAnimation(collapsed); } } }); gripperListener.installDragBorder(); canim.start(); } else { // no animation when expanding finishAnimation(collapsed); } } private void finishAnimation(boolean collapsed){ gripper.setCollapsed(collapsed); int maxSize = 20; //2.0.6b Component [] comps = getComponents(); for (int i=0; i < comps.length; i++){ if (!(comps[i] instanceof ToolBarGripper)) { if (orientation == SwingConstants.HORIZONTAL){ maxSize = Math.max(maxSize, comps[i].getHeight()); } else { maxSize = Math.max(maxSize, comps[i].getWidth()); } comps[i].setVisible(!collapsed); } } if (collapsed){ if (orientation == SwingConstants.HORIZONTAL){ gripper.setPreferredSize(new Dimension(6, maxSize)); } else { gripper.setPreferredSize(new Dimension(maxSize, 6)); } } revalidate(); } /** Returns true if this toolbar is currently collapsed */ public boolean isCollapsed() { return gripper.isCollapsed(); } public boolean isCollapsible() { return gripper.isCollapsible(); } public void setCollapsible(boolean collapsible) { gripper.setCollapsible(collapsible); } private class GripperHandler implements MouseListener, MouseMotionListener { Border oldBorder; public void mouseDragged(MouseEvent e){ gripperDragged(e); } public void mouseReleased(MouseEvent mouseEvent) { resetBorder(); } /** puts back the old border (the one when not selected) */ public void resetBorder(){ setBorder(oldBorder); } public void installDragBorder(){ oldBorder = getBorder(); setBorder(draggedBorder); } public void mousePressed(MouseEvent mouseEvent) { installDragBorder(); } public void mouseMoved(MouseEvent mouseEvent) { } public void mouseExited(MouseEvent mouseEvent) { } public void mouseEntered(MouseEvent mouseEvent) { } public void mouseClicked(MouseEvent mouseEvent) { gripperClicked(mouseEvent); } } }vldocking_2.1.4/src/com/vlsolutions/swing/toolbars/VLToolBarLayout.java0000644000175000017500000002346510573516350026324 0ustar twernertwerner/* VLDocking Framework 2.1 Copyright VLSOLUTIONS, 2004-2006 email : info@vlsolutions.com ------------------------------------------------------------------------ This software is distributed under the CeCILL license, a GNU GPL-compatible license adapted to french law. French and English license headers are provided at the begining of the source files of this software application. ------------------------------------------------------------------------ LICENCE CeCILL (FRENCH VERSION). ------------------------------------------------------------------------ Ce logiciel est un programme informatique servant amliorer les interfaces homme-machine d'applications Java bases sur Swing, en leur apportant un ensemble de fonctions relatives au dockage des composants. Ce logiciel est rgi par la licence CeCILL soumise au droit franais et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". En contrepartie de l'accessibilit au code source et des droits de copie, de modification et de redistribution accords par cette licence, il n'est offert aux utilisateurs qu'une garantie limite. Pour les mmes raisons, seule une responsabilit restreinte pse sur l'auteur du programme, le titulaire des droits patrimoniaux et les concdants successifs. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs et des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Le fait que vous puissiez accder cet en-tte signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accept les termes. ------------------------------------------------------------------------ CeCILL License (ENGLISH VERSION) ------------------------------------------------------------------------ This software is a computer program whose purpose is to enhance Human-Computer Interfaces written in Java with the Swing framework, providing them a set of functions related to component docking. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. */ package com.vlsolutions.swing.toolbars; import java.awt.Component; import java.awt.Container; import java.awt.Dimension; import java.awt.Insets; import java.awt.LayoutManager2; import java.util.ArrayList; /** The layout for VLToolBar (supports horizontal and vertical orientation). *

* When used in horizontal orientation, this layout respects the preferred width of * the contained components, and forces the height to the maximum of all the preferred heights. * (so components are vertically streched to have the same height). *

* When used in vertical orientation, this layout respects the preferred height of * the contained components, and forces the width to the maximum of all the preferred widths. * (so components are horizontally streched to have the same width). * * @author Lilian Chamontin, VLSolutions * @update 2006/09/09 Support for LTR and RTL component orientation */ public class VLToolBarLayout implements LayoutManager2{ private ArrayList components = new ArrayList(); private boolean isHorizontal; private int gap; // gap in pixels between components public VLToolBarLayout() { this(true, 0); } /** Constructs a new Layout. * * @param isHorizontal indicates if the layout will be horizontal or vertical. * * */ public VLToolBarLayout(boolean isHorizontal) { this(isHorizontal, 0); } /** Constructs a new Layout. * @param isHorizontal indicates if the layout will be horizontal or vertical. * @param gap gap in pixels between components * */ public VLToolBarLayout(boolean isHorizontal, int gap) { this.isHorizontal = isHorizontal; this.gap = gap; } public float getLayoutAlignmentX(Container target) { return 0.5F; } public float getLayoutAlignmentY(Container target) { return 0.5F; } public void invalidateLayout(Container target) { } public Dimension maximumLayoutSize(Container target) { return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); } public void addLayoutComponent(Component comp, Object constraints) { if (constraints == null){ components.add(comp); } else { Integer i = (Integer) constraints; components.add(i.intValue(), comp); } } public void removeLayoutComponent(Component comp) { components.remove(comp); } public void addLayoutComponent(String name, Component comp) { } public Dimension minimumLayoutSize(Container parent) { synchronized (parent.getTreeLock()) { Dimension dim = new Dimension(0, 0); int visible = 0; for (int i = 0; i < components.size(); i++) { Component comp = (Component) components.get(i); Dimension d = comp.getPreferredSize(); if (comp.isVisible()){ visible ++; if (isHorizontal) { dim.width += d.width; dim.height = Math.max(dim.height, d.height); } else { dim.width = Math.max(dim.width, d.width); dim.height += d.height; } } } // add the gap between components if (isHorizontal) { dim.width += (visible - 1) * gap; } else { dim.height += (visible - 1) * gap; } Insets insets = parent.getInsets(); dim.width += insets.left + insets.right; dim.height += insets.top + insets.bottom; return dim; } } public Dimension preferredLayoutSize(Container parent) { return minimumLayoutSize(parent); } /** overridden to adjust position (x(top) = width(left), y(left) = height(top) */ public void layoutContainer(Container target) { synchronized (target.getTreeLock()) { Dimension toolbarDim = preferredLayoutSize(target); Insets insets = target.getInsets(); if (isHorizontal){ int left = insets.left; /*for (int i = 0; i < components.size(); i++) { Component comp = (Component) components.get(i); if (comp.isVisible()){ Dimension d = comp.getPreferredSize(); comp.setBounds(left, insets.top, d.width, toolbarDim.height - insets.top - insets.bottom); left += d.width + gap; } }*/ if (target.getComponentOrientation().isLeftToRight()) { for (int i = 0; i < components.size(); i++) { left = layoutHorizComponent((Component)components.get(i), toolbarDim, insets, left); } } else { // Right to left Component firstComp = components.size() == 0 ? null : (Component)components.get(0); int endWith = 0 ; if (firstComp != null && firstComp instanceof ToolBarGripper) { left = layoutHorizComponent(firstComp, toolbarDim, insets, left); endWith = 1; } for (int i = components.size() - 1; i >= endWith; i--) { left = layoutHorizComponent((Component)components.get(i), toolbarDim, insets, left); } } } else { //vertical int centerX = insets.left + (toolbarDim.width - insets.left - insets.right)/2; int top = insets.top; for (int i = 0; i < components.size(); i++) { Component comp = (Component) components.get(i); if (comp.isVisible()){ Dimension d = comp.getPreferredSize(); comp.setBounds(insets.left, top, toolbarDim.width - insets.left - insets.right, d.height); top += d.height + gap; } } } } } /* 2006/09/09 */ private int layoutHorizComponent(Component comp, Dimension toolbarDim, Insets insets, int left) { if (comp.isVisible()){ Dimension d = comp.getPreferredSize(); comp.setBounds(left, insets.top, d.width, toolbarDim.height - insets.top - insets.bottom); left += d.width + gap; } return left; } } vldocking_2.1.4/src/com/vlsolutions/swing/toolbars/grip_expand_h.png0000644000175000017500000000037010573516344025765 0ustar twernertwernerPNG  IHDRbKGDC pHYs  tIME .*itEXtCommentCopyright VLSolutions dD\IDATx}1@PE>)ve [e(g`d5#ex"@k)QYo`D|I'IENDB`vldocking_2.1.4/src/com/vlsolutions/swing/toolbars/grip_expand_v.png0000644000175000017500000000035510573516344026006 0ustar twernertwernerPNG  IHDRbKGDC pHYs  tIME /,tEXtCommentCopyright VLSolutions dDQIDATxڭ͡Pw3IQT6.ڽvFx'Œ,moI>X>f\SN:IENDB`vldocking_2.1.4/src/com/vlsolutions/swing/toolbars/gripper.png0000644000175000017500000000027610573516344024633 0ustar twernertwernerPNG  IHDRV(bKGD pHYs  tIME 5ZtEXtCommentCopyright VLSolutions dD"IDATx !4o/w\<8UdpnIENDB`vldocking_2.1.4/src/com/vlsolutions/swing/toolbars/package.html0000644000175000017500000000207610573516344024736 0ustar twernertwerner The draggable toolbars of VLDocking.

The VLToolBars.

This packages contains an independant set of components allowing multiple draggable toolbars to be positionned around a central component.

Getting Started

Getting started is easy :

  • create a ToolBarContainer (a specialized JPanel with a BorderLayout) using the static factory method ToolBarContainer.createDefaultContainer(...) specifying the borders that will contain your toolbars.
  • add you component at the center : container.add(myComp, BorderLayout.CENTER)
  • get a reference to a ToolBarPanel from the ToolBarContainer : container.getToolBarPanelAt(BorderLayout.NORTH)
  • add one or more VLToolBars to it, using the ToolBarConstraints to specify their relative order.
  • enjoy the results !


An overview of the components used.

vldocking_2.1.4/src/com/vlsolutions/swing/toolbars/toolbarbuttonborder.png0000644000175000017500000000025510573516344027254 0ustar twernertwernerPNG  IHDR;֕J pHYsiTStIME  $ LIDATxcd@253C{H@<4KE . <@9\,\fgIENDB`vldocking_2.1.4/src/com/vlsolutions/swing/toolbars/toolbarbuttonborder_pressed.png0000644000175000017500000000030410573516344030774 0ustar twernertwernerPNG  IHDR;֕JbKGD pHYsiTStIMEQIDATxcd@F$oH,MK fA4>'B$s"m}M3I`Tь) HTd*c '(IENDB`vldocking_2.1.4/src/com/vlsolutions/swing/toolbars/toolbarpanelborder.png0000644000175000017500000000025510573516344027040 0ustar twernertwernerPNG  IHDR;֕J pHYsiTStIME  0:cLIDATxcd@F(ǀtpA @TuLd:مL0Q!yzP069 Wh aIENDB`vldocking_2.1.4/Licence_CeCILL-V1.1_VA.pdf0000644000175000017500000062516410573516344017665 0ustar twernertwerner%PDF-1.3 % 479 0 obj << /Linearized 1 /O 482 /H [ 1636 516 ] /L 207476 /E 86226 /N 7 /T 197777 >> endobj xref 479 39 0000000016 00000 n 0000001131 00000 n 0000001486 00000 n 0000002152 00000 n 0000002663 00000 n 0000002821 00000 n 0000002873 00000 n 0000002903 00000 n 0000003267 00000 n 0000003652 00000 n 0000003866 00000 n 0000003907 00000 n 0000003959 00000 n 0000004172 00000 n 0000004389 00000 n 0000004607 00000 n 0000004658 00000 n 0000007296 00000 n 0000008035 00000 n 0000008265 00000 n 0000008288 00000 n 0000009001 00000 n 0000009223 00000 n 0000009439 00000 n 0000009828 00000 n 0000021423 00000 n 0000043073 00000 n 0000051748 00000 n 0000052270 00000 n 0000052349 00000 n 0000052556 00000 n 0000052840 00000 n 0000073503 00000 n 0000076181 00000 n 0000076383 00000 n 0000077884 00000 n 0000080470 00000 n 0000001636 00000 n 0000002130 00000 n trailer << /Size 518 /Info 476 0 R /Root 480 0 R /Prev 197766 /ID[<27b3c5f6320ffda39af6be5c7fb5d02c><2ab704bffce50a3f24f0af5287f8634a>] >> startxref 0 %%EOF 480 0 obj << /Type /Catalog /Pages 478 0 R /Metadata 477 0 R /Outlines 35 0 R /OpenAction [ 482 0 R /XYZ null null null ] /PageMode /UseNone /PageLabels 475 0 R /StructTreeRoot 481 0 R /PieceInfo << /MarkedPDF << /LastModified (D:20041022175708)>> >> /LastModified (D:20041022175708) /MarkInfo << /Marked true /LetterspaceFlags 0 >> >> endobj 481 0 obj << /Type /StructTreeRoot /ClassMap 45 0 R /RoleMap 44 0 R /K [ 429 0 R 430 0 R ] /ParentTree 447 0 R /ParentTreeNextKey 7 >> endobj 516 0 obj << /S 300 /O 425 /L 441 /C 457 /Filter /FlateDecode /Length 517 0 R >> stream Hb```f``Ka`c`: Ȁ @Q0w\nX)'񰤩zF[⡉Ay_\f*<2Φ\.\HiZԢ;z5]5^S:($ln:Vv^s^;5OSzmU\NCnQUZW0 etA7ii &XX)4- $ )!؂i0PkhDXT @ aƓ l8?& Z ~ 07Lc8 l<}la~@D؂Z z@!afQ - =N2NcI@2Z t-?@>6S8030,h0?( endstream endobj 517 0 obj 386 endobj 482 0 obj << /Type /Page /Parent 478 0 R /Resources << /ColorSpace << /CS5 484 0 R /CS6 489 0 R /CS7 485 0 R /CS8 494 0 R /CS9 490 0 R >> /XObject << /Im3 513 0 R /Im4 514 0 R /Im5 515 0 R >> /ExtGState << /GS3 507 0 R /GS4 508 0 R >> /Font << /TT6 492 0 R /TT7 486 0 R /TT8 487 0 R /TT9 496 0 R /TT10 499 0 R /TT11 502 0 R >> /ProcSet [ /PDF /Text /ImageC /ImageI ] >> /Contents 495 0 R /Annots [ 483 0 R ] /MediaBox [ 0 0 595 842 ] /CropBox [ 0 0 595 842 ] /Rotate 0 /StructParents 0 >> endobj 483 0 obj << /Dest [ 482 0 R /XYZ 119 61 null ] /Type /Annot /Subtype /Link /Rect [ 349 417 354 427 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /H /O >> endobj 484 0 obj [ /Indexed 489 0 R 255 512 0 R ] endobj 485 0 obj /DeviceGray endobj 486 0 obj << /Type /Font /Subtype /TrueType /FirstChar 32 /LastChar 101 /Widths [ 250 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 500 500 500 500 500 500 0 0 0 0 0 0 0 0 0 722 0 722 0 667 611 778 0 389 0 0 667 944 722 778 0 0 722 556 667 0 0 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 444 ] /Encoding /WinAnsiEncoding /BaseFont /Times-Bold /FontDescriptor 493 0 R >> endobj 487 0 obj << /Type /Font /Subtype /TrueType /FirstChar 32 /LastChar 116 /Widths [ 278 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 722 722 0 0 667 0 0 0 0 0 0 611 833 722 0 667 0 722 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 556 0 556 0 0 0 278 0 0 0 0 0 611 0 0 0 0 333 ] /Encoding /WinAnsiEncoding /BaseFont /CLPGDJ+Arial,Bold /FontDescriptor 488 0 R >> endobj 488 0 obj << /Type /FontDescriptor /Ascent 905 /CapHeight 0 /Descent -211 /Flags 32 /FontBBox [ -628 -376 2000 1010 ] /FontName /CLPGDJ+Arial,Bold /ItalicAngle 0 /StemV 133 /FontFile2 503 0 R >> endobj 489 0 obj [ /ICCBased 511 0 R ] endobj 490 0 obj [ /Indexed 489 0 R 143 506 0 R ] endobj 491 0 obj << /Type /FontDescriptor /Ascent 911 /CapHeight 662 /Descent -223 /Flags 34 /FontBBox [ -168 -218 1000 898 ] /FontName /Times-Roman /ItalicAngle 0 /StemV 84 /XHeight 450 /StemH 84 >> endobj 492 0 obj << /Type /Font /Subtype /TrueType /FirstChar 32 /LastChar 49 /Widths [ 250 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 500 ] /Encoding /WinAnsiEncoding /BaseFont /Times-Roman /FontDescriptor 491 0 R >> endobj 493 0 obj << /Type /FontDescriptor /Ascent 911 /CapHeight 676 /Descent -223 /Flags 262178 /FontBBox [ -168 -218 1000 935 ] /FontName /Times-Bold /ItalicAngle 0 /StemV 133 /XHeight 461 /StemH 139 >> endobj 494 0 obj [ /Indexed 489 0 R 94 509 0 R ] endobj 495 0 obj << /Filter /FlateDecode /Length 498 0 R >> stream HWrF}W8\0\TIҖuDV&G"R$ `d !Ze O_VM)/&/ _6M6_}g<*'08 ES"Q()˜>I5*P/mDDFc)04_㛵ek0L-tHTϋ@RNpܤ\UvMϩʃ/SMOup5 Ƴ%IGl_Ǐ(JtonA\ek+%P5"w]d xz:*w`w7y{w|? ?чZEȌ͜ֆ}{hL!GC%ڜ \7%xEQ*>s srݒI"ߗM>w'/BJUέ]>dOTKV9Zsrg@n g@`6\Q;jY ,WoV ,@ʢ/yqfYV5UԔ;DOFr{}ǵ7^WyV/ylh^JZg@b?\MO|OE=6T ?aWXxJRoB Td+/Ы\tap1f,j7;>T/i\x!ujQI/%^WӇ5YM&/&(C=eբcTjʊ3_,N22!Pq7lϮBHva4T73m82mlsWLG[n mEU0[i`eZ0rݎOK S' K?!Ԟ%d" fC;U{I1kRTॖGǻ u&se O_W|ٴl@j-/rSY)%DnL_9}k\ʶ]5!)jt4'x'T4+Gpj \fgVt5M!U‚\H/:N/qk fVe=w0wƕػh|.3)nD"/0;y%j!b䝽"}c(ésKϮ6#_wPO:!`JUOu8w}o:IL2R1lFϛ/ X/mcYs4%nyذz࣫ %mb.{t~ߋwUgl`BiMp TXͬ©h䂿UkQ)xp3[o &Vuq:9<+}cۑ/g֐JY;) 9ЕcĹ *6{?L/|3}cc6xeP`g#L}Ӗ-UU;ǺͱLm/H?,&)&48Ꮚe_]-HjtY<9GRV(XzlUL Bn<)&o6͠S| xp|xG_aMy|8w[TD$i2(Â>%MWW74B<5IbŠc9͇u"c|c2E+r{+=h:G#3 qؿDƈ LhK)*\+͏{@l\w*V$v V4B-s}؊KzִݟC} ~sUͱG\Yd8Vvm]nr_:><(qD9k)ze{oQa9xqˉg~dv0fuOԑѣf#JU$v=erAwH7{v:h/Gup薻LVOfRQ*ԹQU`EgaUh@J endstream endobj 496 0 obj << /Type /Font /Subtype /TrueType /FirstChar 32 /LastChar 233 /Widths [ 228 0 0 0 0 0 0 157 273 273 0 0 228 273 228 228 456 456 456 456 456 456 456 456 456 456 228 228 0 0 0 0 0 547 547 592 592 547 501 638 592 228 0 0 456 683 592 638 547 0 592 547 501 592 547 774 0 0 0 0 0 0 0 0 0 456 456 410 456 456 228 456 456 182 182 410 182 683 456 456 456 456 273 410 228 456 410 592 410 410 410 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 182 273 273 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 456 0 0 0 0 0 0 0 0 456 ] /Encoding /WinAnsiEncoding /BaseFont /CLPHBJ+ArialNarrow /FontDescriptor 497 0 R >> endobj 497 0 obj << /Type /FontDescriptor /Ascent 935 /CapHeight 718 /Descent -211 /Flags 32 /FontBBox [ -182 -307 1000 1086 ] /FontName /CLPHBJ+ArialNarrow /ItalicAngle 0 /StemV 78 /XHeight 515 /FontFile2 504 0 R >> endobj 498 0 obj 2558 endobj 499 0 obj << /Type /Font /Subtype /TrueType /FirstChar 32 /LastChar 224 /Widths [ 228 0 0 0 0 0 0 0 273 273 0 0 228 273 228 0 456 456 456 456 456 456 456 456 456 456 273 0 0 0 0 0 0 592 592 592 592 547 501 638 592 228 456 592 501 683 592 638 547 0 592 547 501 592 547 774 547 547 0 0 0 0 0 0 0 456 501 456 501 456 273 501 501 228 228 0 228 729 501 501 0 501 319 456 273 501 0 638 0 456 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 228 0 0 0 456 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 456 ] /Encoding /WinAnsiEncoding /BaseFont /CLPHFK+ArialNarrow-Bold /FontDescriptor 500 0 R >> endobj 500 0 obj << /Type /FontDescriptor /Ascent 935 /CapHeight 718 /Descent -211 /Flags 32 /FontBBox [ -137 -307 1000 1109 ] /FontName /CLPHFK+ArialNarrow-Bold /ItalicAngle 0 /StemV 118 /FontFile2 510 0 R >> endobj 501 0 obj << /Type /FontDescriptor /Ascent 905 /CapHeight 0 /Descent -211 /Flags 96 /FontBBox [ -517 -325 1082 1025 ] /FontName /CLPGLI+Arial,Italic /ItalicAngle -15 /StemV 0 /FontFile2 505 0 R >> endobj 502 0 obj << /Type /Font /Subtype /TrueType /FirstChar 32 /LastChar 115 /Widths [ 278 0 0 0 0 0 0 0 0 0 0 0 0 0 278 278 556 556 556 0 556 0 556 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 667 0 0 0 0 0 0 0 0 0 0 0 0 0 0 556 278 0 0 222 0 0 0 0 556 556 0 0 333 500 ] /Encoding /WinAnsiEncoding /BaseFont /CLPGLI+Arial,Italic /FontDescriptor 501 0 R >> endobj 503 0 obj << /Filter /FlateDecode /Length 11503 /Length1 26436 >> stream H|U TTfQ>  FEEEA(ƀdF@AEHD6XۑTĦX51?Ci4~.',1$,YZ52gFck5{9| S/LܢrwQG^+[|w0Z9< P?6sԲѯiہЫ%[iAo)3l=J˫7BEnL^W\KZfKNnd<++fW1n^%#}/T3'!W{6#F#0.yˌK;q>؎)4{]P r q- xCePGk5 hc+/G~ePke@#b,ugyf Pqc(HD\g>2EF#d5F< 63$ja ,dQ>b /Jz-`M¿(Ҩ6N-tCtqb&CUV*e)g+um׻ʻl6vBX<9*6N/%. [MzAG81P8jxT#Vz~R|'n+U^R6(GTVxKr48305_ݢnSmtSt\c 8ޞRŵ#98'q Y"+=͸S6Qt&T-IDEYVliB("]keڂ\PO3h6Q+ WUS-ҍBRʡ60,x??Oku2XiVsFkzH5ntSxyq/oM>~i:F2g, 5u/WT&O+2N~c3ø˰øc.s4;=gI*wu&[iZc1ߨ_==Z_c->~-FS$TVuBݪ6v-pE_jdЌC x1dQ*gxg>d6k~>sb `~q~ .])橝JUl/5Ę.[eG1[$Vv43v.Kfy&A`B:=$'J)1QdɇȖkE#)Uu{VbM-Tal "P/Hm@QJĉ EZ?I0bcۮMFS$Xv6)D^e4Ïs9{ r@3xW`EVGԄgB _0REIjpvvxDY5Esd}jn:_A }T.Cy#E%X>M;H쪰ZÖkI`KkCď'3w7êGJʿ1EEA߂Pۢ5>#fsJ1A-MuJj& XcGE Ia W,W%'bz"KnNY##TʫCB@PW -X~:WԸ …0G|U]~+4-KQT=Ҕv8@(B*d}yD!:GT[:rޜ3\L^JMJ頃"T'@yUǨZ+-m-P݁oT^Mi]AJY^ X,v@x41{2öӘIXЇ]1:h ʭWq[)ٿ=mze-dBG(_>o!31~.<}Nce4ȹ2 h ?? ~QoA5 r4p mfμI ˘x &9x3.D@=^9|e祟>fxżz:\>-QOhu%!~ =PzR b`%|Ua`]/P*`n87/ĺSVQqα+/)S%0w{]1})r{l 99k(B́쫃4r [o@ `$O|g~LrunAfg| Kq-u0m9?Y/n-+%2E;s:)NAP%#Y wNZyϲ0'es%F`'[iU"fyw X'h\L) k݌)ԂL~F!%rɕ._%s]Hr]7tg|ܿ|hu1# ݂}8Zg|OqqvQýT,`>8H.a5޲z̹Vv1vY/k׌CV;SYɽK9O|/Ill=Z)26`Z{Wyjw'{JHߦ֋ETgX28~YG^d"dn XRwڶN]x~wQ׊NNcϧziIp?ss<&eb Ye] >9!s9.9\pAhz“D=|L&9V-dޅ?*IO b `1ӓi>@mKM2?l P2s+pyzMF]Їu\ Nkmⱡ/֛_(5m8øĻp s5 L!O &R絥>ڡ7ۏh*SjmԊ34.rhvOQO] T" ,G֗qN(*1Qγp;9'V Cl)/2Vq1oGn>p(˱tb^|r/d?<"= Öåj uԓxGAau+TL JP4(M@ D̅<ob*}| pvAf29#m^Osh2U !0ՐN\@/Oλr l+/8e74h#Іl_ol$Mbq &8&i<70qTk6Ņ%cm'mӊ5AKRH$[7i]ƛ~ڧbN 4KxY4Ky,q1;Rw}>Sr?RSq4bYs*~_œTŔEx~TYƯs% GܱMiS=eCnSEOo"LHɽMcw.t!~e=޵޽_#?Ş[Tբʟ(U/WKݟz/}>K|IKťqR[n<#?#1U<.)u󻿽B<wݎ+ka.9֏XGZ&MEBB,4+@a˿H@,_klQK}߭U|1S}O`.>$6y{qD8v^yW7Q{łr%{ȻwcD3G)w]LWRU!3?$Qd FaxМL*kBn?A h$+UyOVydߵ]+wv)7oʟϐ&"Qz~V4S.whux_MZ8=w໫WņB;C@(Rɷs*դs cɏ*;nWQ:A5uWvHI_:T>fELɟQ{#<o ;z{UZ^?$-U]D*x'Z|#>ZKHo$AaPFǑ4cj158bMd eaHDځ*W9ذ14^{cGqwmFk׮RżP9~B LzM)ovEnMa.zz5 j@wXV={_/w~-x>ò)b{su/ '2c< #K^+lt/#|DS0U#_[ۋ +&P~"Po i/½ $gf F7dd ~Qd?X.KI-$C̱Kް3)ۂSmFؘ2"n6AV`e'p L(lG؊|wIW)*Fr"`Gahz8p= Ww!888" ⊈և I@@@So DLQQQQEDADADADU a0a0A LE L" *"""a(a0@0@ EAAAV[$"r r r rȁȁȱC3<yHHHV!Y Y Y Yddd>9 C#d3`3`3`3ͨkaa@X ,EX ," HHHH*">!H(=5گcse#E0(y29290 +?D>DaWă%z:MB"%Pm6.WԦEmŴӘtN;+9'3"ZXZK:u]*:nus:/h=Bj3H߬jp+5nHӅk 4Pj|P(o6\! bڕ9ǪTjR!o7oiH%~ѳi[\3-algE>NC}Eߍ{P1[Zm,@C>:`N:T\ :#ka=iy7nJǾdhVm붶.+ciѽ3N Ŏ)OӼ5ZonC2z~PzɁ<\u^5mWxfvgvIEV4CJZISeJ&cUR0TKJϡb@(@jncbRa9(Pꡅ-A.b%e˨nrv7olS UKqro6/ W2(l4eObO%牃Lzv: j`J/9 I/UpAxp>.QU Kz*Yu ר% @[01n Z(~3VG^/@ڼwՑ[!*ò%oS߲o^#SԐ?5 y(w~ꔮ&'B S/pyr8?N'I6WG:.6s3Lfx [?|d+ߦ8,m%zQpuzl^~?.(7sDEezw:G=sOZ4#{v\Uϸ;*do~rBsmR8/\_7|J*Ҙ|i^ B,d>eI.YDZ*2F$pyFnù_u(uW=ZӅ5SDNT3%uvŤ(dN,kI&dA3-j3 -(Ž#& Â:%F.J()izV&4OSL A(1LD bkh9 #x D60b-E,6j|mln%sM '?Bx"޿\S_72{g:Bvw$rX}c220}xSH()T](Sk)sʢ|N˿Zq|t֏rQ\X{^OuHG{ђ8׊G[?2I-{}^W]$".WONpRj$"4_a LJ @h(4 ̈́fC H~p+׊m Ycܪ_^.[sMW{6ǷrmL5uȜB]L8 "ȏ#/YE"zI޹JIDܿ#l_!L\/g?-q˯k#{慏ą?~ύu+gW[~Odǿ:-{D+y!oYC3!Ej"E"LRdO _R5nM`L ^ٶrvԙ]J|% e"p%W@e |M[ׅ}<(߄T1 )TD:4)2uhe>~>(X,#orO83#$53665M*AM`&}0c Ui;PHLQ?fTSUNUd/YzavF=GwUlA]e;ߢ3-.'Dܧs D_a"arf#YrIGO=giUv9Hc[M8dبĘ"6@D,G%- [)e@4^Xthb:c/'W4Eh"GDdz}eްm*EZ/Ԩ@JF ear;H٘c`ౘM[anif#%r 2^١{dJn09Fzn=ޠIxWmuƽ@R;/c~`صe|\K_!~$S?b (4(V^@Z-!*l QYeEP|W3|4*b;hjڐ&jS5ka xfN41v"Z7TUuo@`\>I +u!!>y`G<3xW|d{u@ PS7eJ&v)Pj{13;;z,]Vvø.l0L.B$SD‚TvIA&HGhCc[MS@ ^٥$?ZE1wsΙ;={XCTmBpPJsoӧK8=A tE!Ӊ7Vx΢8"H!GũЙ9!NxG^~$UOb|5eOPyQtj ?GzRBj8_ŷW(--wOw\@bv!jv. A 4AbMX}J#cn= ,򝒄 2<<3y'y3,8:X\\ddU J6.体l"?+kvX۪KLz= عHKHՏ_^i} GGatX7^ؾر_'GKE'p6ౕJR $M֔RT*Ubfqc=营Gz'+t ki(&tq:$r<*DNI9(l纸6-Pdt/;f]HOfL͙NGI8BM>!{az\wYto֯^j-3l(|nqYMeozأ5[ 6H'ԅys&V=`I5$xd\yɍjgY8]P>ݧ*Ss4:Ա>z%Rn;}nGwq"Z\9Ɉ?'nJw Q eG"Pl(,B^QFEN85˳|Xg)7)_|Eɫ(hd5SN.ko,q\RPÌI]4^kaOP?:s㘊M07e>lS$aӞcgQiRr4ar`86)|p-3rd tٮ)LIJ&F;"12wnh{ؼ,'̂jG|dKyD^/@V:-EDO[1rkF(&K*,(!k谇y[Wיkg ySH~ E~hXԩXZ3i/Uj\ٍD =% V֊]q5b; 4CII O&Xgl~fp^ dK3B0Y%&' ؟~0fRb 3޺ {ͨ= 9EBr~Sfg{|m.n8".9zשޣN:n@^Ik+s0a+)}!6* j$$9tRX]Cܼ|sBM;cp<'ϧnlšKرtN*Gۚ:gvѾDavg#!Jy|GG^խaJiGw`l {i@6 9|Q"<0:KOh{Nj۴34iFk tFhnvX&6x|\]ې Y(WKbzOzĥV9)仨UمUߟj]|9\I\\z Ȕ1;+gڂm7 cq,B4ĭi@R=x'^ ,X` ,X` ,X`o.0"MC4pCC6z(|բcP kQ*f3HЯZ!>U@!4MAըf=QZ>8!Tw{g2\߿ I)̣!4rA33u/s咕dD:$4+0 3o&M:*Z8oȉMKzM2?*Ph%h$)i}aAᶢ2u>oC,(wwА+\ 3Tf5U1W.L>* }֭ t$cs:a endstream endobj 504 0 obj << /Filter /FlateDecode /Length 21558 /Length1 31796 >> stream HV TgrBr5A.(*$Kb$!RۺN@I&dAhZ*Tc=Ǻ}T)^VWVQ *j{۷3{3}cXOP8`rNlq 2t C<Ɇ; Zm*QK!9 טȷ9b:|kI^d&ܽPڃESv%~l^ES {ã0>h=@;n#0q΁$gS.@xyK⃹$|AhUJ%~,{/axY\km21SF ?0F@Xh27.0^ӽf׸ VM .1D\|tuLy`궡m:VAX>{ Ń ӢۡYH0IT`̗Q=+HnɥXh hb#m=gD,#1EvXzLժZPVk2D)a = S( ]-WDAr1gr>{ 2io;:n gt]"Cw-xk/Wj ^t[_MMeo!r&q{Í>9~m OD<,͎ڻpcsڸ+7b XajxJڨ=TϕY.o+JOn\YW!lDC|Ut'}԰tQqe9/[g8L0#Ai_-Xmy(T.nYyX:_eQ q*̽ڭcQA+ >YvF}=AR욶EY> wa<>' >W]k _<9LIo¯7o_\{g嬰X˗iTA)m+'oi6ڽ&cȎ)\p'r&yʌv}FniBcIvUtt5jǗlcZ._T qMV|z:9Vޝl7 6?|rf O?UJ{agy귝w6%A}5G'$mpuXlx}%]j*;cg6[*Prܶ+*GRt&E˫f%yuY:v^׷4O#f#/P$&Ox蓊P64Yp+ԑyt1$`fj̄jU_IFʣ0II2"RXAȓ~bY2D"&) M:K"ԙ:fAc "dReDc1~| 6&B( a$)aZrqBaB.=_ŘCpʌZ&ro̳?nYD1?ÑW#cr`|X. 4>oW}[JU{dhAw 'Uj_!I>9l dk(LSk-]ѐ3q.v +K3q6VYx gғU>Ԙ8W Ұܒi7=\ t}SkHF{G79CKpwc,xsz.?O ~W|Xp`_ގUEewlnSqr𠴎1O:-u87M.9;ݗW\60rؼX lfwiwGս%>lYZe/4F,,AeqcaUm"1QOS76T 7ӴS4 'mɳpaqy)BSBjhD[KTq a!MJ!m&@e%Ӊhf D6NI C+n2H6p14A !7HDA!ATzST+>S)T(#Qq4!UEbvG XRGb##:s8-fAZaAf2+jM^MNPeeZ&juT6MUOTmaNצ'@}f40# ju}IZJ鳴j}P0NC}cw<,#`SQC!J4 0,"*F1^7*F Y%1.th!&^HQRoz~W^Ue*9~x))`7T+C=4(S"lr: aA*"+/1dj5UwL^xyR|1)*>8L''W(xePxLOBW Re!a^.UR* 6R~@lڕWdbBgOjd7~2.YJXLФaZSuaUtq+P_ˣq|ZbArJ:Ǥ`WHTbƧ&xG`ȥSr6 f{pM}|yso)v.OI>o5^ή^kspccK2k.&"P܋W,1n}onɨ>E͌tFgS?mDobIDg;H!4ZAu*J T =V=+"e%^x,nҀG4;$A饈w2Ѻm]I=F6>':p:tHn}?:|T"w 8_Ysdp&ܓ+.\bQgL;'>Ȍؚ6ԴY>[+7\xt+vusX)WU6N7l:hԼ53jlxa%-G]ў˲5br :6fn?NDWVop{UG]fh7{mG#Mxk['[9Mu[pfΛ?suŎE$cՋ~ù LvvwZ_!m:.?d-UMV ܜĄ[s[-g؍=96Vʤbrߪ8US5dڸ,S#[duXMf&i\Z:iuQr֖'4`¥p eJ;k+FHdn[mG.FvrEM!rԘQJbZWA0n5SHr(ꚮ|lC`:5ЎG#|>wmkL9 fg~0ZF V/g{m!?@ v#pm0 BD@6l\(2r sG\&HR8L`o) 8v/`ԬD۠G5TX&l1/`)'`6` K]]F3BP`%-1p:+ƉAǶTKľ9B'̎ IORF3 }Wp̘&٤|Fԑep59t5WAp6h'\dW o J!謎&@!l=p|aoO&%&GI+cX29̻L sft Å2 :AK渾c 3`6>b1bѥZ AO `#{ W=ۏ<4J-| pnA'Đ ۇpJLR@֑F9GVdրQ:6o]f3a0X3Vf[ z=z. ^ǰ 7` cDĬų):XBb@B9&2|#kcQƓ)(2H$!ޥ9v SnJNGQ.tѹ4.2Fh -}B f{ƕFb2(!ƱlǩCXd"*EEdžWM] Ƨ zb!ws&6ѳVeFa"SBڐ5cpLr6L %Ic O`4iSpwLr2a8NcGFnkcmei1lLMF"?j #**?W{l?˱N m3a# @#dIe#Z@K"F7*Z GP5tLdDSgFXNlШX*MZ*mh@c~iڟν{9FCF;y ҡLtS->2 ,%[7C>"mExȈ=Q^'\Qχz+[k]xɢ ,WS"ї"+$Q#$9^YkPj4B삥T;pՖflXeM&XU ѻ9:'GFܴլatoZJ{(V!k.WHíQ5z֤x(ٞ F{D[j"qD6F[}0%FaDET*03wa֘;te2;L,Vy¢KkWwhMXOF U1bYJyc@oN3NNnL/tDIs ^gS-GF#(btx5,?V 3$d3:^mG"6QnkGEKrhϖ*R³_du )(:jrWHb7F3uz.Q*f&f[fqK<ےneD3-t3]ui̴cU$sG=sı&HD =0#VCwdSS/lfCIXc. IgaF˔d{E,)lѴqST'L{mMmVR?q9w?RQ矢oKqn+v?[i2LӁ(r u/i2Fa{%?侰 ̰uˁu*'0&GaZ T3=רxêL5R6=o kWiK@~c;G)0~X1fs|8=FB{]۬زލL!CN&󃹡^K?fw;b=3{ lSmNb~a—S-LV*CT^:qrnr^d8L[Fc y7#SŜe\e[^GX{ 3\I;Y&hhjaL8 g-C20}Gg|C΍5<~򜻳|cS$݂=OG.~q>9ߕ6g'˼8x)oo7w9s8wqگh|fk?B7}TܼSR}ޥBoRaUC/sCG|Sk ~Ţ^Q";z`-b-w|}ؗKB7_s2+cQ8 P ;ScޡyGĝ ^p~pc9C` >iw3|BAǦJр{#87?&eʝԧdKuEa}!-QN~X)VѶ ى;6H߁nZ>N F_WDs[sD[69yh_[k*|w _O<?*(D `>xz7PԻH]皽:N9br#/| ԋ7~`8\K|"$~s{MrՃ(ŗ5[!ѮObxY M]h@^իmU7uU.jrzQJv.uIאrnxFq۽=,w6tm.PCl0L wp1/lc8lh/kC`pU١ -QQMVPP8D;iZ;oݝy3{3gEK%G\!6X~L<-^?ohfϬ䩖L^Kxy=~mމAlnlZT '.qiK85g)XD!`.אs0\9ד Gh9& "IO?~PR&ҙS"%qE_dP--5+KҒ8z,Ee"ZHX"F=P*'Hl"DT#$Nř $BXqގ6E[ՏCIhz؄:E!9/9|J.(GBI,Ӕ ̾hk[/[XKvs6֬Y(s~[]4}Kva( FQDY]B)N@ gnp$&ޫ||RW>h6uLpz(`Z Cq3aVRjT-uX;gZ[bت-ccc/[/ƾ+֊OHS[$)OrJ#eI4AKVI̒I$g~_[~}p Zww%Y~tT{uqW:/ {~@|F RCh?szGT7$ג(D;b9'?oM3>9[k W8㗌9|o0OA#~I82B8i\M h9maxWon60J20]J#IoP@M=Fd I},Sp 𬖥؊lYp!"v!bp`2< 25P!h[hMyX#r!,2+gEYU'iR#'壩XHq\6jq̖""D[|{ymbX gs8 2w|Ȭ5->EN70(Km;8_P+j}<6 B6bhô[jVD8ZSaL<4tt:R 3)wI={=N H-<P/֚`Yf9$ fS"(&w&fՅj&ozD:G}Shh30(Y`4yfw82DIr3L8.!.4{ٽxc'{l3P}-MWO$3s̼zOlرル_JM\X9 \8)]uU<'LYF r9&,Wҝ>G,IO-Y7BHG~O~.>h ""yw?> 7JoX;Z^aTHG ByIHF,vF [va&iXȅʆ\k@R**x<e0 2!M`^d ڞUOw,ZҪt~gكϣ=Oތ c[˹8=32i|;5q]|DBft@% # \z)gdQa%$ xg$5Qj@|@`<FmFAtV4F r# aSb^nK\6tE!ܹV ڨ _6 ?+{R9a:]gأȏ.MǤGUd)L G߫z- c!-s:6beP#T~~mɱ)Wx!aψzj@U|bLO㳱*2 ,}z.({^!Rz`<,V]lpQC9< gg42%!%<]u m}dJ^1#,:$PZHTGuN >`M3\SX߬?XK{w7|}ߪe:W6b,:MRɏof|0~}{O٫N-cS pl!1sq>sZ!5q厧seZ*"e~ W>Nzb/8wˡwn~K7 2Dr9ӞhnΎ[E<, XE0~:`ҀJ5@4ʓsGذ#4x@5> ( \;;gD)*b"A , w ( ę;G'Ҕ.Niμ5m{Zm @c{wZى딿k ?ȧXܓ<~l5x腓tO2,1Gjkfh3 N9rS,WYEOT*kiʡst{8tirI:hb$ڬbNvYe$;#wk5>MXlz xNA8i.uH |JI[bBWUbj!Y]hݱ0P>: V&:%(ꡤlϵ{mHVd#r.eNNogI_臫aZ`ggvfg^vmv #').*nZ z] Qmh-b~ (Ev i§Z&\4%mӴ4(jԏj$.P`ǽovqAy3λs=͂@RqǙN9mд- A"D$'㕱J"&>9%4 N*U$hWj4C`Xcus0`9z.ls* {`uO.t*hK1u}QhL%by u{œ2$HD2$IgJr,Z|GVDk2uf5Ϛd:F(\}Owg*IT_!}YmRb;kZ'#~ƈvw2 $]e#4[LvUCiS2} ,fBÌ=g{b 3G&;S`64Lrlla硆[$T:IЂz̑ N<58>%a|ucӬuYRL=gYӨBdVOȯ*EjR)I_@6!.I&Kb^pUwHw(Yrr!h</Hat8 oe[ ޛ܏/ -E[)/EbRo ty≠wPA[KD(GJj c(%(cmGK).is0~ C1ox:5﫞gex,W}i8wވ#o$8`8sMAoU͒@)0f%^i@Z8Gʭ( *>tZ yGѵi^ 6u:S??I"~ !o*ϐ>0 Vs>?Mo]{w=ԶɆ>W޼?Ng4r}r B[!/mz%2^/l[./˯=Yy@yY2c[ʖT== :p|b+J5 7Yi+Lԍa?/b7v7v ;(>=U ]hS>:5 +"$ 'iLmE"Ja2{%ň^)Mj,&Эn,j^ֽzo}]٣փ;;Oiu/A#cWU͘K|]Jkmѥ%%J&͸ub+UZs>p,z%#KYH~4)ʤ J|$( !$ڋHBH}EdEK$0pƀ<D gpQ--;AsUVUTUSYZ DIIdU:%U J$V*P#J q0j ५QW!KZS۩#xYC4`{g6Sr]o Y0v"ؠAUXJjQku0#谅Ix'a< O4a\I8'!EVS9I)qq|̴ZL ZDȖ?>SpFNP7M%pDjn ^ 7j02>HS=ӧEݞ=zL}>Ktx?N3o%&A~ʆV6`#7T[m/kFԡtrLUrm1GkzizZ.uøߕ,9~kH/ DjCi`'be9a=wr2d!nHfUNr G)q>1"YSi1Ytʲ>A7'89N*;J|bԬԜDajʗF2vEEAI34MU, NtE ڱj8AйJ>(ŤÐ?Q܇'0k axxT8̺(m>ȮLH,̭8_ ɡ]A 'A鬧`%5E5n?0/0xI'ferOޛ?*Շ`;sܗGEGk< 2=_~d3&6=~LG T|Rj%OMYVZY{pQ#-S9{S08-P2@*c9DO<ds+vSWA>Ug+b&yp&5wDF"`9~E^[V 0sP,K}"UO灋*LM%; w(F)5}r%ߪٱ8\κ~qω|=[Fo?joRS̺wN49hl{U9De llXݮ~P+fQ/b+`y8a̬Gq-: w^|By?²ML ePexJ/ ;%nhr6oxFY2ގ-n3&.w4lK]N`huaWRJC0BR =̤́T?`Q뼆3pM2sev^]lMgނO-Wwn~4DnԱ7^f}ǽLt۠-Q_av׳ɶmRӁbVq'c75̮!l&t_Xa ՗Fb-P`( 'qdp:`q:Z:cܴFG 1@3[Ӄ_kͼ;t]6Mg{G! |ĕX( |41D T0L :]?``JEJIXuQVkf{IZH;d?*`;\>M(Dby;>ήv|1 Oz6Ln[~tsGn(oun;UDUcե*S1[] 3 i+g;XQ!- ]B,6{5EKJaF vwtyGݡWՋUUD^u: > OU6U~~)T3nY9QEȋ G=IĕJ Fy+H4$Uib3k*SXct ˮ\bc.x+KwR?U\_4h؅:urԇ^SZ^NÓj׺Pjn4x䆾˷[m]P|^43fn~O13g핟]~$)::x]=w?oK ߑ?җ2'c?OIdKxf[Y$KL[',`"dY. '"ϱDpp'X X@#UԂԏX f)F]I\ 0ҦDɞ0+p#To-8ƏQ-j vudӹWm@ܺr;0H(sYKpGhI٘FۏHkM*,es w2ܯ870 V2Ύcr\cZNgȳbkb;bcc"sT 0R%M%P~xt*ԛ3@ 6g#m uPIUvZPAjWoL쪖fx?C-׳k}09?gS@ߵFxa:Hf$L@vۊ0:~+Rg184t?Y_9㞱6V[cWn`4/ܞv2[otYPYzO׋F3͒׊xSq" 2B-*S װf'A$O%Чȥ"x8#B]%- @ K׽PJY`V }(~ WW-b42d[_\=-]oR}tq${3- gsB&C*n*3Ve8\\\1*X6!J'c{M@)m,(njtN9-L .>6"첏8|kH}1v؀m;`Ju  6 R(N(5‡IT(*ԁJ8-CP T*8McbUV[J;{vt~<'ˌ3,Nܳ츝׬yVn3yJrbD(E%v@xDEò-wR/6nfB뾎K1WϟLS^n^;Mf,5LR떂-3zoAhz1zzi/> v vH(i4$&> ;mdcj!;DwTY5{ƽ F0V͚31ZV'|m꒵~o+_)[B-%k /яȟݏɧ(-ĸ`㤢^xlԖ߬PE3cfmSVߝS;0:aꌗﷲ _N7kHQ^) a: :+Emò"pG˜j5L6Of oLҵ2idq.[˭ve qD&yhŊ={x{MQgb"Oҝ 1ݚeƫc!7%^?w\礼D"hN,]2,kMN/|dV"L8LfU("ʂ 7խؾpɮI5˦?sϭ:IvOjI 4F9 kZF b("۷;hV ܮMv}  ¸hQB4fmTR*"]HnMC)9_cOZN &DEk.k: .RZvK 5$5A' 7 */> >ƊHȪ+VR-@-%HnE pE$;:RqSD~9Oy^O&jq(WWM2{7Ȇ/.AlP7 N8?\ Wk6Zb/lN͐m1[GzIJlG8\0 *:)\̩:Շ11mȌ"d*6[(0%mܶaN¿Z 瞮ȼRrSiBܹ&n +M2On >,)<:ֆvPq#$UP{u+NBOR:POfn8^HɯܝE2Kk6oXG;kO 0Bg&tyn#ۨ^Jo&Fr^'_]re AsFuҧu$>F4%@G(sI_1maywm^ @0J`VDWFG[e$LpaБh(nY4̍#8B%~pߜ F4.5 bń}wS3AQqVKQƀ2 h?,Yy5($qe~\Eeaf˕ W͕s)OWx"ҶgZHֳ' R)=Cw &p*BLv}oV}#ׅlά")C24dN3VG0=QaqK (Td/=uIֈo/`ĽPBRtTIk6k!HOb$1n8= mLP@bVKQIENySiQXG!2ߩQaooGgXؽjc'a!\ފI l/'.S[Crkft *d6 `.1,1VP9 {wQrT2= 7H̖0bF+S|Ґ(:F "kUZJ523jgSNi>/j`ҫYOX0L!R峧 ]! OƜŬƫ2N{Fa~^u>l/Y`Π-& OJʣF:&+cϱ79q.iCaoWTn:csbܵ[\b Iiei7m5IyXg_q~ǝ;3>w㙷\}Yᬅ[9MkwNgම_@|Mlu͆-Zĉ_mrgn f g++[=_p[vO1@鎲r/**w^ .kh6?pɧ5nk\SW'kF| @6HՂrJxL]wBȵB(hЍGVO}W/NNjF롇g h6٨yCfSȭMii6fmS<Hlduc, {> stream HV{tT '\"KB@$ ҄DnY!bTAC{IyG((h@DRh*EOX¡ GOޙofM@`9$~4+wtu<ͻsyGZ6wI:$>lu6vַM_Va-ԗ@'yfloG Һp뀁湁zӚA{=} Mz)w7X<6iC-N1=m;݁4%)w/[pyՒl-c:x$5hj^G؊ԉXLAo *d$inA#(֛ki0bB,Ay\ͼJ^Zta&ȫ8Cxؖb[lhb:ǝ!(EǴc}g)Vh Ş۰p֊Z.M'E!^4b<C(])ʦmBq$#INC\Ŀh -M7N>4^30~,óf6>➒!d%P*eH*YH[?!Ƌb%m2XMsR*fYb6+[g0da:Yଞ ϹZxm+؁A8ph 4h봟~Ki[j}oW)ebtp{89kʼhc3P˞wa ^pg F.)FC4ʨ*Z56&2hGsޥ2}CYĊx1L "G< JEX%։b8@gEqMܖ 2p)4Y%el]Iy^Q~JT١QSTnbmkl/^]]?l/7e萎rGdzE^gz%*ާ#:dEeb'He __l%( !?i - 8Cne'mav1_*c5().C\m MbMxY$UxhchU5HɘsrZīT^qxs4ւ:+h('Oajwp%13JlSm'R[r< ݘ.nL,ߤ/I˔zQ V,>Yb :e'o_ɍ=J+-Lϝpޡ.CPDcACƙ'p=mRRy..bb7QLe<~߶hr/qQKY(1_m_j_r&K EE샓:WH|'g=jc5*.C]ם־eo2]U@=yi5G_.mƨQV_8 ?&'{I*>ج"?1w*@53r_:}/ r[J̱$Jo'Q}xg`OCAIC\#/WTŶdv?G'륌>.z).#RĪ>eJNrDq+FvHNqϳ"?o,[0|w~B?_xq䀕LQ2Rcɼuzu2WkSbV<:WpeZ< >S,j-"ķ ƈ#(ѐG|XXjhXѴV^ӔfL:fF(ID}xE'Νoqٳ)F$0ȭ 4کQk*^vxз[L׆PF=̦bމVn{R|;myEpw3Ư7@p10*k@+粌HgfTB}q[áGe\(OAV墽6g|?\-{ >z ړ!' xz"D c"`>sE Ch5 !m lK|zl3mE~ȸ8q09'nu,u m":858\AN8a~)/fș1>O"a8ߧ!kufX l_7WGauX?>;U`R>cAf`ni>zeb Vu}Oo>al=ϲ};{u߳inKmb/({W>g )_eBUpޛD?qjef]/ftYٳ~ ^`k4+݋&fVwq[Z3#m_4+ifb?NM" 2ګR /6;ϞL1FjRq' Zi4E)rA lx-$d|0?Rږ9|Jq-O U~@VP>ϣ~,w[͐۽_e[߃Fp9q8v"Lۿ6 =?_± k}`eQԿMV.kg}_ԧ@>MRyL"Gųw)Gśw)QQZ]m{h̠M"; FT?snD}A9|>5ߧWTc[o{4w c>{ghߦIc`T5we"9Kݦ=m|m4'W@)Ǻ mZc*_"%R|kY G2:ܻis)G]1>zoGx{b#r|oUNhqg1~0-Gc܆@-_E̅2==mmSe(RD(G;@% 4\Z{mzxMZ C0-s3)Y8oC\z41j蔸<ىԫhnhƥk(c3(p55y\?f c.)vߪ!8Kz65ZC~>Kj^AYˤb}~zBאS=Sz\1VZI0z8q8r V bIľxR)d^!jM`p3F>zkhhK7zB7ݼt3x=7>\6Ȼ2\w euџdɾ}׻gXO0Æ99xmsWޠmo>r CDRGi\E{#@ `P, ɣ~))01y31I)<&kG{I^\FtљV#N؉y;;=eeZKPiT\yLU@UFzyuUQ^UTe*T9Oj_3~M5FO,%"&AHI)Y\qe2LK`IXOCRȡnpDO9pkUT(2-B@J[:~| 'QVY-o$Dv9Z^>Mx:k*/8y4RĨ-'}F>ާUz;'| 䉔+x qjG%L _z/eJSAr r ׭~],Z%CN=c{h{wۛf{G!wMmo;;Nisr Gss?ˎ:[1LH( UѸhUu3IUWդx7q{:FO:Y &06$Vl 8EД6LI&C)$Biqe D M̴ v҂RZ<gL螴޷?~~%S# W"ߐQ.(R&#\ =oŨ!ĵ1m胬ڷvܾ;Bր-`.7UjYk,7r.۽v/eE7DNe"I# F,6n>|PC]?]T !5*hMpN{N$WU'pY$Qq5\6>Mpz elp=1OUeY1xVįB\.]*^ qaJ{L}DG =HUVVrUJ]CU.q}w3o"𞊈S,qFhgm[g T )s!]^ҕnc˶u'S]"M0cliy U5U>lHR#% =WQU7O&&S'N~|R@Ex B x[6fps1 );X&ϑ9Z K)D㹽/@$G 8IQTOLsܦy E03+Y!E}c ee˳Lv5QP$&ӡa V}w#A1X =9Un&&, RS"R \Z % ְ 6e.?7K9=q8B2i67׳ڠ׿rw7~bg;?!ϱ1#Rf>!0| BXFb.ƾ.po̠Ű dz:J˳z C' d4cHA g$[0.@ic HYE)kwgt 8,)E%g:~i!m ! p1Gf-T yG&aTXnT4p;]t:V,Hʧg|U&[{}cK,Ԋ!eB2iffu&e \8I0Mm[;#kZ.kZP4y[ӛJP^6*Qk)uKz8/9lqe v9Ju21B5Z3R"12W%UP5#UB>\()Si P𡧿W};O^0L[SX3|7]C?ϙc?:wsmqֻmѪ/;#8B4sJ\Iz4VFEw ՂdSlEbhGZf_:q[X oV~l!&l#8ظmU[KIH')]V$BnMXK!防t8m,J˱?_p-=podyu3)GvM%. * IohNS˶?t~ ENdB"^ "ȴ|L͌8ћ~ř!i=YQJ%(ldȄ I+}4n"t𙭾2Yw 'Uxrgs'LRy)&u|u˴1]gs!;ִ 7zWۻn}^e/Uu}}~s؉#E 4#+eIǠ$6A2hZL"bjkPOՐB mj4ME 5cEƈw{6&J{wϽ>=0^xquڂVְDb( ISxO=~]w6Aӭa!؜!Eԋ`TcP! ] aIXE7P"K kes0IX`Yd Py%$ǤndhoLNgKJN kvnח5 ?(撟gFsWl@DF/6e *-cMbYmrHVhPI()o)"xbBI 33B A6QAP$iS4M0/,/<ĦUXxY <_titC ok'ǔd4ɌQk\^"IBXJ9%<"(&vR= 0 @ 1A!X~ªp"UռAQɜF&cB:UM9O΍;:5 5MmW{!ra<ЉzŗvA *ݝ.]CDdS<ELJUK^!H8,k<Ӱ7hӕ;.>V|d/}TE<+~l+ 27#u`}SF&ۀL)[>X.Ro?U {b i{}#åԶ $OnwNB(& ,]}")D-[,QZIK (2_)l>wp߾cgWc61pss8c/8;kOU # }A9&)LTu =1B-#j|HN@ĭ)v&BŒs:pjh%٠ 0 ־SHi:E[\t3SA8`f3Cُz3 4.^Ie\x"4^xke=W7G#{+ϔf\kbIB0ߞŞ"Wqdrl?`vpb_W=Ri*[I_ӅHYyxvZR.cH wx!BHUq+قUm,eO!! S : Y9ZP1#Uk.YPK~}wML|aD)8EaTIV"xF*y}x*'Ncĕ_١=V]z`>ޑuV6'.)XҥMJWW[7*y|k+? endstream endobj 506 0 obj << /Length 447 /Filter /FlateDecode >> stream HO٨򮮮߼a]TJkA8'֨-XwOF;"f2͈sϹ쿿ƌ{󲲲nhhhWWWnnnDDD___·[[[yyyrrrPPP}}}kkkcccTTTuuuHHHLLL㦦 Ѳ<} endstream endobj 507 0 obj << /Type /ExtGState /SA false /SM 0.02 /TR2 /Default >> endobj 508 0 obj << /Type /ExtGState /SA false /OP false /op false /OPM 0 /BG2 /Default /UCR2 /Default /TR2 /Default /HT /Default /CA 1 /ca 1 /SMask /None /AIS false /BM /Normal /TK true >> endobj 509 0 obj << /Length 209 /Filter /FlateDecode >> stream HLDA .> > h0nUwUUgf:ΤG+b=⭟ITHԚ阶1U'}OCj`E!"hν?$]Ϩ~]jfcZ>R3龹J1R"F&mz߬E$e&ZOGutt2::9_ R' >׿f endstream endobj 510 0 obj << /Filter /FlateDecode /Length 20571 /Length1 30276 >> stream HW TSWYD3  5qLBDj_re%C\V&'Ý%i8UD8Ib4/yA(EPJ JosXyP; -F DctxZ:LQT)*$(W(ZeCcGW $Rll4H$?OPX^ͬ'y(B\cs+Gvz~OkyklA97fdSwz)kJ+UМ_{:0+1!gvڍon-9lq|1;"Nc3Y(_K #Θ˟бӹht~Іx3 ~;v>[:Ӡk[.[F7ߗ1%WEaaNEo"*;qQ`ZH3$Bޝ#hI LIz*b18 IسhtQQ-$BELpD*24!s":)D:c$cQ=vd< 6T%BUO0 FTIB/j1) aR sLDOo4ңq7I2 %,yH8;ߠGW ܓb0ĻMV*O=&[ſѬ\:eKV{]'F|xV{W[ðeҬ6L [x;WnvFv\~DLNAW+CΕѫ|[΅fq ToO;3*-kLܘ\/Y}CkB[;>Zz?nã86ygc4h4о?SR9q“.vJmg$|l)@Ź8g3XfbӯlӀUT3Y[Z.Fw2 aN6ff0bBbzmᱹ"1}0}8EBmX̣i8%LOB*M9UJ!*!jjB2 j2+ZMtJ JW*⯪GER/2 .JTx!eg84]]xxltX *jA_m]^{Fվ~ ?9ʡ 2aPh4aR#NN EPp-fyxZ]V~aZFMw\N+Uj_ԋ㻯}Bp:X;X((U&' ~*F(T*Bd )rMv rAOb`Rzr1>1BlU\bl#|30321LbQ@ȤX!=!y!D ѩ)Ơ$2]LԴdCΘdul78Gu19VߤyxRj|K|b4w\nVFrҋpaUy6߫$z7JKmzC)V@Atgvw5EHJr20~}%VqFR V;8Oj;ȘzJ9b_l]T3_`m{v!^?̾QvDS7C\e S]ZO^y=9ux񅒭_X'Mioa)E/v͞U.JOW̳qXti`Pmǥdd7]=SYmG:KYp[Ljv)0u[.E  I iRa&3 b-R co{KΣci Ŏqx Fj#+kknpYU?SQ) ~2cSH=)IN}OeMI)ljΪc;\kݕ/[+:MyiʩϽxhGS^63sz9>=)ݵN}~cϷ'ȝa`|o]ǓB0⩩DB)eñ R)UUB;"{=l w%r` :7INMDub ,h? ū>$sũG}s@<lX ~*q/pO>),b%eVcGřp ~P{`  e ,<O zg _C-\*0L,B Y0`TP' X F:B8KL/c'ύ&p?ѽy"d =!V'pl ޝ ,lqqP(wct%nȺVD"bD!6179(&դ\$MԜZP*TE54FxQ֗ 1Os\ F 7}x5_+-ɇ~u`VDAuWMsURR@* A^?%sXȫ%d%MԤ!t 903҇-cǸ"r 5#5T.jINSGf,,%KC#0"7"`{J'F!a.qOZYD7p: lz ;$S)Y8f9ϑ)yWf0#<=\e1.Ftt/>63| .3eHJp lb\l 5MLH✝WUJPpEMQ9\P {Ϝ׺kVW,^rE + LC'%cG5vKK=0zJJ#լٚ1h+jf4DMuVҶĕm+:迚3%OȾ^# 0D0JV',8VR^'yuTWn9z"eEvTrsAx%DR vAhdOL'H$S_'AW]TJeuCVn"r;- V4 T$nD隞hɟhR|ʶRy'3zm+d oiܝ LGKi-f=5޹/Уɾ#H\Q~='9"ha=5jZA!4IAKoڲFy >F;/SLdjVQv*ꗩM9E62mw0U&o^[@;ɒF0 ;^0=:0d/axkU A>mek}27{X}]]povO@G>K>]8,Ў<1o9o ʵZ G(y?_bJ{ cosqۨ=B{3*6Mg)3y 9@hy}~~øDg1~hb`8ܡ:Ȇ3nO>2 k}Ɠ9.; ZVN`/9'M-}BlA^>‡ Xk 9g_<[r0N,ԑ[35l U ZTorq;BssC~q}/wݛ ,#K"zPƧ̌mmoW^}@; ݃>0+۠{9S7I*Ѣ?IzvFd &AԘρUUZ"S?@g- !;9,#05> mBf}J}HR -o-exKJKx01*?j{P,*gO)ݨDwgP&SEߍ:51~0;U|? /윛Ku.\JUI5Wv\9Nko|EL>WA~ڲ9=k5u$:~|d1Ԏ;yxH^A-vOzx޽kvjUkR_ƈ{Nͼz OeLFouyCڴv 5vPN}a^л'^kk";zSB~ع-oc9:LZ/vx}2cވ^=c/%8ȹo_H["aB6,s^XcYN6҈)P.Q9 x?7 )wa!=x ^+Qo7F{[L#=yuM /wLƏa㷴c`YL_6y69On4nE~ЕM t+Ikw ~GOMhxm_1 h4:z`Ug'N1*ai@]X[#(-%4ļfk_Ͱ݌5Cڌp$j5GqLKla`RX)i )HR\Z\ S플ɃLXͱ!%[j1 }]vB<0 ۪!C,Ys|KNH)W rʮƲY}}e?az8rǿ!^ (QP H$ނwƈrN8o' GKU1`7lN"9IT*jFx[ " 8ef1iƶK)9_I% ZHBZ-EK=%!=+l'>ð=b<;_"# M@>/dZ,}Z-_ /׸(WfW1佪=!2 ޾ t_̓FiHԏˈ=R$3Wz!j:b4G6"96j^,})9Gp= DE+wȗԣ=)uam1[·P]ZѴpk4&*{&dS2Tc`|Z1gV3 d zYˬ0;DWe,Emn_uOV_ʒ>5(9Hؑ/3JkuulNwD&) }Ǥא$,C`kg,(IRF0WF#(eD/D|—]sE(bh$ADFKp|LJ88PSX*:4*GL7dx|lPs=PY[ :5n:ߓ&E{^ɠrz+>mD}x*$B ՈTըo˩2=Q[u51|=]ubp _M͂ajg\>i!@G͔F۔?ëEw5Pޔ꭭Y W/̻pG]GDNG΁I^֋e,]G0Ma#Zqu**\X{jpoqMkhzIrgÏr諿rh :M8ꁯo]v{+죁PФ^q4C~Cwzwz5\jl{H6||~ u+~=_[eMH}fdc6KU288N̹>5QA%eK(KJDeVfe㳐I(^>[U9PjOf @3(rH}>(8:8#7WB=H8頢#H?@#z9dZsQ׈A|~weGaٻ,ˬ1 U<->U[3։ҵSX'KZJS, )+iaVRc'/䟤; Iu|=|_$d $Ylvwڹ|k8'z1Ű]X'SʉI(ST\\` &|s?0^wv{3_37*k0m"I6>w wI>i%]$B dRIBw*EmmKy8a TF(i~b}^/z+ "3Y,^{3D:[dL&twم|A* t{%yIXSIIޟR*UPY\*eZ 쉪6`"x >gP$\$ Q(R,ŏ`FWYoTRBFKJpx͋}zXX0b11Fm(q8~'N=HARAz<5}#5JVVÜO"fv= ylaY6ʤ*eU#o1)nb)^Q.(3ϻnvv@<8C9DO(JG"g?8S)8JMS#jii{bcǙX)mZmfQԘ5dJiPL{s{< 4H>9XXk4dm[b Rs>,,s\ ϫʒM搷{x+١lmU(XgLv.pUWiAPSẝX,Fz'+-/xq!>1\IY[Xh֬Ֆ|GN^^fӞO1m]uWlz§"?5!1r{'؃jZLZu$2H,pV,I, b+ȏ,4gua9"12e%r h'ǵX@xQJơMpP%X(-~in>IY*x}kk 3O۸E/fRŝ&zQQcfjV퓛n[Q{~_T5i1lwɲ]>!`Zs\1(#y2 +w 6 ~NpXW6hn1H`pxÀ4ңCCM@.c 9NTA(*w'U}`MK7. 6NZ:qGW 71|122𧗍 G &Y>9PzGrWbHEqCNpxY =&qhLڼͺ"R Hd6<jEc53lk(?>S6Lu $(7! 3WS xfUkF97}||ʖyꪲyUJɓ#s#Ax6t>{-!:dFVdclVH6˜ X,LVKȦ.^WJ6 Du0 >r~e ܗ5vφ| =9s X3.%sL7BB)9#O8z,%L|Z9ex cN1Ըi0*aY|#6?f _ Jd6GB%Ϻ_%UxkULPʰ(5Dp""pxQLnZm?r^!1B O%%f!PHV@F_̑鎈*b Z1|֙pMA_ ߩ\*p'Ѿj]iǼ J0ؤ\1h`||N/k<Ks\ד4czԦQqL8 D̛Qiz/,^fq9+'O׫N*ЌJEX)8.Zb4OoSC*%f-OeՋpL;j*s=ww.0B& S0&6&0BȄ@BiR(`դ#t/%$t1锱X@ ݍ0:{&}} c(T^~2p_c1!@aΦDdcd"_#r|=Ɵ CmgT-}ާ˞xZw~`玎5Ʌ3ܥsP;kF?Qp&Q^&t.`bG-EHddA4ff6x,Dj fbIvns&"{YͪQ%;$r"uN,ƥTNVR{x( vLΩa>GpXNҙ:a[fǑHFɨ}cϑ_|/|g`O9E?NO:w}~ja߸{gc.%Kyu߈~WU&y YnI$OnJmgk$"(Sk=eY+f /@b TGv&1ƌVCiMy3~RpF}Ͷ~.zyŬfѺ}C=(L/~uv-&ܣh*5nPdGU {_PV!7iCa>ˬ7[M&EW&FjlūKHeܖ+#u,]HD 8Whyklˢhu'nCYee`ݬ6_i`TJc>:@!4Bh'-)z[e"@cZ>?mh Y{їi.ľ9}P~iTd AW/r ދ);E(9iϒ FV^ZrJo #oJM k zAÁq+YO3ZE/'!!$kSJ :N3cnc4 <옉&I;WDߠf=9!/f}?s`r=  l+Sw "uAƂl[`Ŭ3SncƘn GDabTa1.1/[ rsdhg=2ŖZp cLqOyJߖ9iH%}0wOk&^+]r|[4781Sd/1Z}1 }:aٶstD Ƃ@ "5 @ P1# ]KLȵ\ ]#y * L0̗^n-\H~ڡz 0J\~ lk\QFP@G.٩9mvGE(DUU "VZ`%vz!k^j֧t*('˜T5GQ\ؒLY=,T y )٨ElYA\a"Ҕm]o~޴aæx|Ηzxh -6vcІGYtsu[o?]U7 |kGnq@i+>Gdt%o6.S=1 e|r4mL!+l^^+[pΩ "Mev?dkc⼮<'MccMXZ uҺ`MYR:/t#DEBO%̤9Nerf#agDZMEEy-v}*m޹{6coZsx~,CDw܇l@0̴n1VqVχy!Qq3'9YBHh(=RK9"z:qfp/="uW_u@vd?bo"*0-dlcJJxf(V>yZٸ=jZ(v8TVWNiMӸ֟lf EX W(""p+_u 8myD!|X5skNjB١}?Ih;v,}$cRG[7kvF66VH1?2BR ә.i)pU(¦F.#":t heYLC]ږ%M0}EXaaZOALPH it M` liT;ӺpskШQgt /IA;yîX6ž~ʒ)Gڐ=<0 틗{wc\v*ZBDWa^0~w1J{`r*qYAJ%Ax7w0`^9ЇtJt}sI, bOн N㩴5䮯yR*Z@J?;MxtUۓ\a6`d:tC=k"sauE}@41!|Ag8F )GHN| 8$. -.\-İ⢎F:Augl-4tqli?.Hn;5 C)̀z-|.:0sXgQ՝H3]A1d hNjcJbX&%IV`<@sSP'Ԭr#*/> }X8(%ycg}pz \rV$0Q6%JK,9Pr̀?Q3Rs@n Ԭ5f9P<[܆T^rP[~D?/t  5Gasc~rDUj}'qĔAMS ЫNnIoIevi9SPLAyD5 VTY(Jnl>(FY<3Px4]˾]546M>8KoE?ӫ>{rײ[Z~֝Y ޙm*[1[ad&ru6q|qwcS:lK#FC &xS N(@ #*UdW(T>UFhlʪMfK{ٲcq3q6n[ɯmq1'~!h1()bN)@t!ul@( @{;[9%Kq [M[i-`h(BP)icpy?˗kpݚHvf&?^tg PΚym)tN+Vkûl]R$Ce8LJgidwc08cP_11nOSX΁9f O:TY)hX֔ӚZ#V3aOrۍoVtL1i4|(*Q(Qc&": )@(C'⢖،웟];eL@Ϻ?5ِ߽ҫ<pu LZ$?.&v 6 lq|@G)SrS+4MKS4FC8LF.9m#w9ŧ=OOKN,] $VSCTG=r1h>:#}^t]NAdUJatuz ޔ;"\^xM9 eRt+ 4zh.w)^>/%hXb`O{B%t  \#rBNɝrZG<$2a&(*Y`T27 rH?SЍ@{6xh}KT1%Tr|-ϹHI}/ezμKo-cg+ a0px^(p{fTm>e ?4I+8QIbil 2S&m;l%s,۝N<'!Ρ =) Kl8j@}Wԏ;Q9f]h[Ya+*3mUuc-r2bjgO/N M~ĉo:YgGMɇԅW26d0M@z;m1IGmsFI[s'b*`ގ`t k5#ʏ_%KؘKȏs]Iy甌ϢM2P(xÜe1(h@6c(>6e~oYa5$v@۰`< Y~ϣ'w_\; mO-\;td]zA-26dݫ+Ⱦ79~Ѝ{ =19GJ na$NAU !7Kr[8)|"\n y9b]RΠ F k(-m폚ʪA 6HrjR /y߸ + nD=Ss*C&0Mpɀ]; 6i^gV0X^&|Yl5Av)pKa~{qrcxx} ٱ;5Η=]F@uO&Xdkq}UԈEdXbBLLqI)T"JVFR ʐr  x7RأɡF3DŤ!j)g'W,w|q81==̿aVP' Aǹ%f6'* }~ruenT6JV/hg-Y|_VY+bX3$Yv{<%>!P)Mv)De)tѓxҰz>+./}_g )KWxy7|q%Il`C+QcI#M|iRc\m٪On.a ;ua߳(](LY~(,!s~SV=녁9uV[P~Wy \LY9E `z0$]EЅtq*oI%h!pᎵ<[ U\ /5F^r.{_{=s7}Ҵ3{5k_<-`c3?LȍzLMDfc\Xy84M? >ŧA~H֔2%  >]#M rRTO@-o?v۲mIl+0Qg_fȎc_;x8_]Az =|kF3bnuݻw>X@dqEȭJ(i;-ӔԦZuJMǀmbNZԄh;NVљtl yilg={ݻs}?u#*5hVD?Ҝ6 nF:GAu"ED5O𭘺ݴË8Ŵys0 !.C7I]vN$'&adދWHe'Pftf$2vg0ϰ8D֮j䂆4Y([f2oE'Խ%Vnj$/n|;kI^0==ٔɎ-\de\X6 so3j;8hօ`cuzK?<9?de}Ue趡œL/RK]fJZ ny va/UTY^ y13Ɛ!Nl\4\?Eΰ3 @;DID2]A{ٝ(i{ג/ ZsupfƊbN"Z~̈nmuu\iMPW:'N~fm=dN.|(O(ƅAwD1۪ Y9xEAd~--7ʂ(&$ِ$Yx~)c Tur$h`F19I‚N-YAX*:İO)ƓvZŁ:C.$Dra!*punǸrf 0}a'(o8 zt&.>dMiNKn Qm%%m󴐑A7n>5X{{'P;8=&_8a6C̼{y=]MƬ׋FGU7`utl3*G$BRBZKa~P7UdH?("v . ]G: %&88`BqPdȦ+בlI3bNuFovp8=MpWߑ8Ft;,?jkem,ҭ5Ƞ~8%BΒY|FF23"bb_ޞՒگ4WƢe`;lk{A?OE*hAC.1TC4>LM,SlG}G<\?aU[%4 >|挕cQ3y"ɂ%Q8LQQ~gzѼТ5- y}|d! bR\[~~e描n|цuM0%2678ijܦM:Yo am{RԴ_W*/AM%S?ooq| .zjk;juwU[>fee2pʄ!sRRB!bcQ~$êtσLEp"x})ԴYsrp~A$Z/.)]R6wae5+WEuG֠Ʀ浨; m_]@RAb z V  @ 1> stream HyTSwoɞc [5laQIBHADED2mtFOE.c}08׎8GNg9w߽'0 ֠Jb  2y.-;!KZ ^i"L0- @8(r;q7Ly&Qq4j|9 V)gB0iW8#8wթ8_٥ʨQQj@&A)/g>'Kt;\ ӥ$պFZUn(4T%)뫔0C&Zi8bxEB;Pӓ̹A om?W= x-[0}y)7ta>jT7@tܛ`q2ʀ&6ZLĄ?_yxg)˔zçLU*uSkSeO4?׸c. R ߁-25 S>ӣVd`rn~Y&+`;A4 A9=-tl`;~p Gp| [`L`< "A YA+Cb(R,*T2B- ꇆnQt}MA0alSx k&^>0|>_',G!"F$H:R!zFQd?r 9\A&G rQ hE]a4zBgE#H *B=0HIpp0MxJ$D1D, VĭKĻYdE"EI2EBGt4MzNr!YK ?%_&#(0J:EAiQ(()ӔWT6U@P+!~mD eԴ!hӦh/']B/ҏӿ?a0nhF!X8܌kc&5S6lIa2cKMA!E#ƒdV(kel }}Cq9 N')].uJr  wG xR^[oƜchg`>b$*~ :Eb~,m,-ݖ,Y¬*6X[ݱF=3뭷Y~dó ti zf6~`{v.Ng#{}}jc1X6fm;'_9 r:8q:˜O:ϸ8uJqnv=MmR 4 n3ܣkGݯz=[==<=GTB(/S,]6*-W:#7*e^YDY}UjAyT`#D="b{ų+ʯ:!kJ4Gmt}uC%K7YVfFY .=b?SƕƩȺy چ k5%4m7lqlioZlG+Zz͹mzy]?uuw|"űNwW&e֥ﺱ*|j5kyݭǯg^ykEklD_p߶7Dmo꿻1ml{Mś nLl<9O[$h՛BdҞ@iءG&vVǥ8nRĩ7u\ЭD-u`ֲK³8%yhYѹJº;.! zpg_XQKFAǿ=ȼ:ɹ8ʷ6˶5̵5͵6ζ7ϸ9к<Ѿ?DINU\dlvۀ܊ݖޢ)߯6DScs 2F[p(@Xr4Pm8Ww)Km endstream endobj 512 0 obj << /Length 127 /Filter /FlateDecode >> stream Hb``PPP000ppp 2'1qAAAnժʶwNs`s[~ʍgC?Ƿ߿ˏaA  HX< endstream endobj 513 0 obj << /Type /XObject /Subtype /Image /Width 167 /Height 46 /BitsPerComponent 8 /ColorSpace 484 0 R /Length 1331 /Filter /FlateDecode >> stream Hܗr:E`* b?9-pH*뚚"?a{9?ݍ=Ӿ![FOc*H%Oa*`оb2^cP}_hbtR*nA|Q9@r-]D M6p3=5\o?ic>Z_+i9"?-e\7fㆇgmF58Q'Rbx )HZF qd:, hIEl.{y?}Ch"'J1]#fIE9J4!Sn^FI)TP*ׅv˔}wYVq3dERjfwId|Ed|`rēW\Z!GKƏYAFK=ZQD&6%P*8˴dB#Ĭ^ab>YĦ0 ̓ߨκo{ˍ1=#@!UhgV,B3^c+Ny-%6cK I"+`}ʐTW&c&-!"h.owj9GJU9c?*d.IYɨ Fj2]FĘsy S,Q|UgQC3&ܱQJ,5 "GF' jGhbBJN[af D`gwN3֝@ی)+7#s[JX&@Rb:+8j[v$Mv$!!U;MPRpWgs01Cri`S* 4}ݲt{^jzyS*wE\5:Yԉnq f0!&vf %\,^jdM"ڥZL.$Vsꄘ4n񐕚(,QIƃZƻ ̱(b1Yv۠O}5;B@uHUr|dAGy^)V$4ƄSZbJ^E4uDy=m3K(: #*WMeQ :T> stream HW Hf{g9VP*Jcvg?cA2!VQDh—^#>~ٛo?Kx._Zs_*wJ*u})W__WE=JVT?[ӌh<Y5O4UQdIqʊU,vE~k^Ev`yKlLqYmM[ 9b#.Y:#<-mCs]VKC,HHVfP ԪeT{PZclHV0rۿ+ &=flXj}R ꖋz=Ԃ&E==[)&Y*f#>Ҽmؒ8-yV.&sK rwkj=js>N~"ݰF;ɜh[=F%cQUmyOgdĄ'ԬyeƗ:=~N?WbnhEЮ[;~:P͇[:KtTkV9viz[쨝u&^f؇r.\M4?0*]ա UAl@fm}Ȳe^] 5<[C޴xl}~y3%[MH^X/sK{8lba Re&x2Pmay[)4褂 XHe Bg{X dPo}$o`۰#$Y6'?x!h*6!끆ǐQ   t"[һˇ4tR0ު<* {(As7YHeq-,mXf>b5Ha%0n[e`bpal C$p )=>)kB]7[ŁntšcGQ E+LfʳP҆Gq3/t᩵ǧ: 1,>B#J@7Ak6j! lt%]̃W3{G/q0A3ϭ@(bH q0K-F觇AUIP@lhE;4˔(ف+ d`#Ϊ?=wBZDO8B-Hde;> a|Rpn^xMڅ8ȺL+:䴵F^x $вlbt3梨l0 $t~sQX^Dl4*{Іj|2f`5=x!g1P;6[eg [D:P犈zUd@G{\K:@Ĝ-螬O,5"[º*=E9rHxyaƳ QЩI"SR< s9Avvm7҈dL{/MlM[M=mXE78>ʻL6LX>fdޔA22hUTQjӳwMm34T1\vW\AMXݢj]s2^|jJ0@yĸϽ@~Va;:c7٫xdLŃU="XG%ν;i_ 1G]c;apOC8.)5T88 He>ЖsD֪[:=̀yF{/Qx:D,s> stream Hܗ_RI'k+s7*ĄD7Iv]jK좛e^DE;s8Ϲ$ 3g: EL=BХ_.{˜Օ|ϣt*4 A*< ArV{ FQib{?[Qʷ%#eWe˳>F ge@ٓQ*P]q:z[vUCvGɎk*25;Qg;27ؕrcy[cuF#>f9zT"E؎v{eS&Cv0TO2O5uj"zz١ _V&?uu롲zAܙM9_Ek\=O=tyQ{..ÞȞӖ^ʗ s.gva[Eσ^0w }Y3ϹU_Ut71o:k(uj Rz w .8fEmmg~YP:&Vy`yȅe'WRSyX޷4|_p0`ͭ!G2CT/zSloۤ|`.#ޟE9-F;fP;OFǃߡYr9U-@sQ)>Zh| XB NM`i`U?oƀ߮ݗ-4*y%$h`5In(>~ u;*ۣjk\lxQA<&:*y(WuB*z7d@-XܫNJwP;bܮK\Fs X STX7`)r=a\BW0M.QkO;BE*{a>΄ ,yfyBRϵH-1>gu XBȉlr@]؏$ݢs2SҨ`_RZZ 3j?nj{q)^ݬ,@|iY*֔4Fme`~V!Q~k8u~˜Օ%۪)תZ\r}xpZ7BU7Q +! e4o| ^ 9ksbsh%=JUY]bR|ӵܓajj6;*쥐;´5MR V-ԩ+ bf5 XɖP='NirMZ78X-CP gTH칽]Y<z6j)ɽGI{DVPB_ԋE.)NjǴR/:|5Uh.1*03˜=oeZbf)H*8+*V6(+t+O$lY!cXC0v\b>yTc:(eL+TX XmwH `V'()%++6 Kq*INioգfkä-O۴VXZDVȄWTp Xjy= *=W+4cebh4"dnF5m5U{NYMg&JYcxEvXq=tlP|?ޓ嬐 ä}c+O8gT1ͬr k"G<8 >Ίյ݇g3 XD^!+^f#yV(zxŋӬ|p2dzlJ0"7pJ/9!*rlj%=(YV,[RۧC:±RtxQ#NVXFb9+AfOEڌP j"E0N,[Qp')n.ce t"9Y0ҕҝ=%h^:Xs#<̂:x:)ĕsjn6ڵ #j]TDS'td3F6bk7.̐S*qj-[Bѐ HqvӠX.Y} 71]sX&dO]0s*㕠^!dpVs2 гNQ=p|*P=sqJد}{>fyW@I8wtgwV/uK?,߸cUZYyKJub2T;>q4;wybꇼxt9Sb=LyY:@phuHWSBB%T` >^'\qzt]/Czn3%#;yK8kl0~\1!/v\";t}e=F6 #^ 1^6]J6ߓˌEV),Lu#"p$\[|MrVT|> 5ޠQ$B1ejxVcbl_A-gB ؒf% qNHD'g45唳76T[߱{tҢmvȻ@#vyy}y!ow~~gN?B:+܂A!+*fG1T-VB@uNfB^ W4V8VJ*ŻoUAƊ%۬uީyRc-Uh7FmW3YʊdӔoxw;_yz*XQi҆-XQ*[]m%nSwMIpYZ{ZʻUvt_ѴCF˾jxN 'fW=Q0|t ǀըOUn*XIܦHX)jU+On~ebm"<w# Esm-J6Y)ihp=X4_E%Ve@HAzcX,4LX?Xt񔫴"Λ{Z"Xb(jNrA:0jjt!+e]˄Z$NZ=8{X}~cM`u! fiP8+܌8 }AŨ$iH5I,Z!60m;bIHb=Yl3fhIFfnb5%|}sX]0B9%mAi훯.VYf{ +$E+r"jsvm2݇Y*v@EeׄK;#G 6n yX/:&ƯŽw{}vt]v^)M_wv^׏¶pi,ݔ߉^5pKrmH+S:Lܗ.+*>}j'2in;7">bdq뎱YS)Cؙcq^#ӶEfxV Ο߀Xmw_7ܝafbB33Nlg{]kyp:x7zh,+K<͍k}+`&=C*(G4Krvbc%)7W-th@iG~'L:NGEǬi7+X-ZJԝ,{J"y&ye(GZZ#TSUSأrĬ$(BuPpZ5? N\Oֻ0ponj0ToPo">DBnkݢ-ajoI"{;PaX~F /+TЕ¤4*ma/ՄKB"lז8@HI0'1BULFr `X5;eLP*?JFsV,y-Wձm~b V00,"G,EwS GA5վ#u6MX4VfEaE²Պ$myIK0`m6}9T׵a^ }y8DE"4Pږ*/;Vh;ŬHn/Fkw:XUdyoO3"o=HxW^ga[6V'wUWPVT }#0@$w$9o'*IjX- FiWȁڞ)ǁrS.(x.X9j܎ۉ澸1um߻=9P9'JI2T3+ƊTJ+RdmI5ROeo@|1?Mwߏ~3i dEC6(#( O.+ WI=Ev[5D#lU0ڥGdH0'DwDIƪWEq| G𒨭aRSy7R6j$Qbk4{)~DT7 VMv%VQdn<[*hciAcj~a"rl5P]{ ={%9Y:< vY_y`59(nFyr'L'`I5*wA,'6ḃ > %^r~{ Y;o3<%~3`‡ϊY>œ;} g ,r֕Q <%Ϭ7vMJYms:> /ExtGState << /GS2 507 0 R /GS3 508 0 R >> /Font << /TT5 496 0 R /TT6 487 0 R /TT7 19 0 R /TT8 486 0 R /TT9 502 0 R >> /ProcSet [ /PDF /Text ] >> /Contents 2 0 R /MediaBox [ 0 0 595 842 ] /CropBox [ 0 0 595 842 ] /Rotate 0 /StructParents 1 >> endobj 2 0 obj << /Filter /FlateDecode /Length 3 0 R >> stream HWMsFWm?JbPJxSNMZ pD%d" ׯ{fu?YK?0[l->Lۼ*ivݶiK--nnt'e 4E&:&c~$ Oso6U5/B_?JORN7[ʓWEUyFuƻYx"$IG/|_ƴȈ Z⏿p- ٓ=z2;ΚL!2fΠ}yK2P0DI18F6kK]@ujkzl2AP&e R劮Wز%31Lۡ1̮uC*r@#,$f|nZ/Kx7訇]k`_E$ ('46CrVՓKKo%ǚt m:e/aBNtc3'-J֖aWg2!T[:Gr=ŞfK %b物10Դ_mI0\S\Rƈ0،9=iA-ٺMQWNzjzHe?Ib!CHNSM\kZ02Q];]mǸMݡjH1Pe}{/L/p%@3,oZ#V9+ ѮlmMkܱi٦FùurB&I ±͞ΪՠLP؃B6PpNt*U\3ʏr~W}Bn)_@U/Nɞ0H#nrvorbXxF7ҷp$*tP! uU_|4u$KXں5вj5;Ą!wzu縌eMU=|L #+:uByy"M?i~rI8]2l;9j匼+; mY{E[Sj B?PvK ɞ f4zdk^g`5M);fBsdx\%&$w, $K;zAifStZ$@_'[T,ge|kdQfvzţ+ZJ!^6$Ǜ*\x5vUݤ/iy~I#Ϯ.فkI0_VmhVG]2o: jԄ~k)zZ4ѵň0'ٜ$|PmrbI>^dJGyO&ҳʍ3wA4&4@-3u6qL|U_҄cKňb \Y1=°ح;ZB}NOy<ؑC3֘tQcz߼44SUXDZ&ȉ_X%1>Чf|xуG ?rm(Q{>^ۡOx~]=,( 2QЂw>,Xv{/Vlol7BSDO$wțEn'eŲ !ߎTAW.<*c X6 ; `\L8*Nۜ߄^عQ;K`%T,Nj#뚨:$EJEB.?@tF&h FƴI[P]/bBpyg<ɴiWck<{əF"Q~8K:YrlXf'+dD.ktr %r Í8WU/ n);1yLm,^fU^vή6t7ڶJwo z†nxH)C?hp.zY8>2.BIMV2B!$zB&B*w'>' 91ݛ1}ցؽz߱mpRHggl6U4%qci/c"G~{Z_n}a?Lkkb8lE{_`n<b5 W`V endstream endobj 3 0 obj 2302 endobj 4 0 obj << /Type /Page /Parent 478 0 R /Resources << /ColorSpace << /CS2 489 0 R /CS3 485 0 R >> /ExtGState << /GS2 507 0 R /GS3 508 0 R >> /Font << /TT8 496 0 R /TT9 487 0 R /TT10 499 0 R /TT11 19 0 R /TT12 20 0 R /TT13 21 0 R /TT14 486 0 R /TT15 502 0 R >> /ProcSet [ /PDF /Text ] >> /Contents 5 0 R /MediaBox [ 0 0 595 842 ] /CropBox [ 0 0 595 842 ] /Rotate 0 /StructParents 2 >> endobj 5 0 obj << /Filter /FlateDecode /Length 6 0 R >> stream HWnH+j x&4HLIgl`I4U٠H5I)>$R:YĦ{^|f-뻗%yyUmfvM>_U;̹͛D&*&  oެon'irINV<ٛ|k:H.&mV`1/)3&s0| a%vӍygl,ջ_+X#Ә(60ڮG>[t~ۛO+F#A&2&aLBEL+c8Ev#o޿E{ '}Ƭ˵KSҔ} eS$T!1|0[Fdz|LP>pP }O6^ Yg ?Kgk 8ËSL.hN5;7gGz~}dwUcRmH7Cm֖y~%q>եBZPcdSE~նiЙ ɪ-|d<7dsͭ@V&]ަ$zyL1ԈFaW^HyLl*̶6-UWv|ahtq0?.-uEz+\1wXeh"F49 y] G{ r>O:id$Pq#--Gk4j۠ Yfwm_CR쇺 εp\&W3lxD]7fR>\p-x|СgBHk W ʱCz~"婔fF))Mw:W4:4 )_`/B*& W: l$ӒA Eӎha$ Tl䗎*; xφ+!p@he}vx7:]a̫S[/_i{ݗk[ehHyۦBYU:h׻]]20.24\}&ǓyW2h'V!5FrY;s.Zݙ%nr!$f gI&bTcZ}h6jqI܇^=/AJgG z-)bt^=WZt2!&׍~rH1O{ 5]]7(Liޥ"I"r6@* _;4P?4-r^a"ؑ"R0xn<NNќ}^+P~] Ⱥ(ˇe98GM]mjˋN3p AC(4T\dwM7;$&B<6z4Ӆ.%W ,%^@ $hˁW>-k|YD jI" S˸a&vkhi. u0Kk:Ӿuo1}FP#X o«".>\f$,pG$`U{@aVW KA'a6D3#hMvEgJ % 69?d}Wg)@j`LqR,RAH}r ᆁba ;ߜ寠$ `M/3n8 Eh [&]GV^OzG};o_N {CZ0]M& S;zuxx>[G+@Vꇤ2\I&uL(Sа3j#1!!޻XEȏx(V=3A"A@4f_vZ%/[M]kq̐Ș{k])&'wVKWDl:G}d^=jǞA^u'r[8ؓ=',{AT~.ex't`n22tmś$ͦ[*.Hf6y:qd^f~}ԭ&R-/'ؐbs!yMUwul70|Ldv(9DB^G^…c#o6۷}aɦ~Df7Kw+TC ~+jin9Ǥʆ1oLr%YW9#1 H}ƋrJ^===ߣ]H@E\6Fͫ~ \X}x&{ses/М6$7FyLoGFܺÞ[:rn9VH*)RL{}89''xބ#-"בu0gPBs!I[qG.$9\p-8\p}XOp"ej.h$pE‘q9n;5uӿc8;"-N\@3G4Oy1 /EңƘkj=0T/a&uj[^9KtcMD[|$+;S^)k+a*IΝ~ԋ@u>&O3~_}t͠dž˂ȹE42B<ь&nNjk~L@lW])k$ѵԻ./O?l+Y}I";H4٬Lܩh1SI۵T@K^~{K:G;/-$g;lm.8S8v ~Lv<ܝY ׇ͡ G>&Dc暌 3asA! HF k0%✴ytoc_i^Q~J&885Rw^]IMFmⳓ’'].S$8@زNU9x\PbA|Nfc70P=r£]AciqW`P)^! z9_W|عl܇yi*dÀh [`lUcL‡mP |֛DD7~۸o> e~)ھr5*%` d^lEqd/tV;wM{(7YU Un ؒ8'w9¨pӱxK\ܹhy7%ZVm<'It PUR[?PW}UYO8 "-~$>mz!uҏ؇_7\jTf?S&]Y{VXTu 47o?_~X5\ [UqwV ȭSH-NqB#}znO F`spOܑ6̦gMdy;1rM&IgXOmQIGQQTT{X7{< l_KL|84H7f_Z"}ލ#SQcCOFaJi`cGf1^췿Tt ?yr #jW1HEhw"zt3-beȽu"$ 4Nٻ浞6ǤT0u-t[w;FRAZf[ 4 ޠ֌nJ#U|{llo2;j߈ H ۘ>$\+Ews}A#IY*[~JkOhF띡=L2'oBB9?50p,^l\Xўx:=fw53|=w)'VPv8jp*.|"L^sIe:.ߨ| I٘nڹ Ԟ LVQBOR+ǘ<5Mа{MSN4лAWuмiaOflJtrc @XEn^n享if2EGKRA$݅W@%٢I[}Q1N=>}j~$9}x?4Ujr]&cM_\? ;#1٠Iys]80p+nFiӤ4+ِ@B`@lL](_lX-G|\.U!Q=̜Xೢ$1rEڒ gjir=} d˵ CdO} 9j[ʐBG& 3^|@˶!s36ma&0;x endstream endobj 6 0 obj 5704 endobj 7 0 obj << /Type /Page /Parent 478 0 R /Resources << /ColorSpace << /CS2 489 0 R /CS3 485 0 R >> /ExtGState << /GS2 507 0 R /GS3 508 0 R >> /Font << /TT5 496 0 R /TT6 499 0 R /C2_1 22 0 R /TT7 19 0 R /TT8 486 0 R /TT9 502 0 R >> /ProcSet [ /PDF /Text ] >> /Contents 8 0 R /MediaBox [ 0 0 595 842 ] /CropBox [ 0 0 595 842 ] /Rotate 0 /StructParents 3 >> endobj 8 0 obj << /Filter /FlateDecode /Length 9 0 R >> stream HWr+zTiZF#rL%HdR$1!Z|}nA$jat}9ETykxfq8Y9~[OR TFJ1$~|tr9}`()AKڿL E)\ޛ5xi:/ҍ4AE:/.hrEQ-&L(J9%8A +XiOl&fz+&&+ KdMPb5Pk$Rf/5OlZ;vBpn Qm TFRCa2|^zMHK]"'yR=1gX6.#7u0GCh"̱֜ 16 nX&k7c >MЧhn?hv3?zP@H|s @8LS2x:bQ'F|l=P>MT[ ٨HH׺V]- c6&PiPy$.![-D/d XDD1~:f#dzPZDqm\o!ԠD"/JKg6 ϵKN [ݦsĵbD̓> ~ag0f7 zr kuM-~@jd] aQ:I1Jv`>PK"͖8T;'B6L%eafQe h[][Yed{$w.WU򟦨>).RQ"xVI<*E j1n$?kS~Slh`;X$06CwQ _5z@_n٧ 9&D5 h?^Vt#DX'Lae辽, ) @ ;Xrb.W\5S=]َv%"_'vfP 3xd-7,hV.htJa= 鸰YK*&t?$,q-IE3dqTxdzP(rq&ܪS>lI ZX~-,zKP3=ӧ顸r ـZSGm2!8MzB_]uLx`4^E҉#,׫rl~ j'wP)-EoFQzũ{Q28aY-``ZTeC=%X]iלޑ𐔑" ]Scs)yz *CXpc8o8Պ6%qz@\+ܩx#` qQuKf?!zN6j xbHXN7u pä4~.q&ttsKӥgR`*gNӘvTzfPk8CTG{R@nEHfo80 N=1* &QОJeGb @h)UHgzB+#;VA1i7  E'b!B[C0eU *j"= r,ׂ,5M`v&5j~0?JLf|J =zLʭIR4oddJT_H%wf [1˗O"mE`סq^EEݛԭ!gwCPǁ+05i: -'2SXYj|gBrcl".aE>%5کiU&"rJY k.>H(G!6ڍӘwsТS'kYyTLba`"ɷϚiqƬ}z߭xHpi]be[YT4¼0Qۖ{gnn3$.عB/%xs[hbq-F^jėci@He@3 Fx&e,MBA{Qxe5RoA&:-Wv]fBg&)(زa1{v1t9 + 3g@ak><`Mr 2A^Ȕ+|ۉ˷qa1 b?V]sa >^$TDRHRA4șg2{]&qQ|(B~_Ic c3(~'HW x `MZC3]mMݻu>P[ VM%zz&jÎhj=)] ʹ D]ZYV}h[\\E]67 y2TXulQI0F |\}wߢۇ!=N:w S$CE t8d} ,"]-Sa|6 \k;;%dלa۸C4%8$[4 E{=8|_KS:ܞZ:!Hv"#4رp%-3-8󰖊NIFAs>=* jd=I'Ϋm W8t:#vLR?DPHб Վdًg1Fy5֝ѯ!%FF:2CnS2 GVaBVR?l[R0KQF7HNPg4|r6))(#w)ӸHC ^~8\:&?J!',Cmӝ.J*9R |{Z7 sf Hm9F>2Qĸ$lLbó$78;Q޸L(ޝv컹bYYvxOæ%s %kn9${I5})KB'fI׽??PVzyn7(+'I_Fpzd9/sJ9jcH?[pTŋG_ʣ59^(p"f=UYHV>r2 Zr] q8v2Ÿ^5AjmiWΧtv9lŞ0x^Hb\r_-L**ȅA'\uLBBL3 "ׅ_Ml'oSs: NL \Z1T3:MiT, `m?ZC֍sqvߍigR&N\OC7` a8QI9 W٪v}0t yΈ w'@Ḫ8aR1c;p#zV=y;4RfnQIƖi!J*'>Ι#2=P}4)絘QDB7Y3N %av.tH0 5Wdюb1r 3 J"UyKĨIX1nz{.'ȏs)<#xl_w٪4dFD6j[sbsKThլ/|VR,QP)Y Axn0@~޾n6&C$Gg P?};Dm{IuwгZ%'7+v&dƨ>q5G¯O1#>,CA(0tZ)uk|)Az" `m&AȜb= SJvB#"WWۇ_EkU>X%3M 5 Qx˨Y0WM Km hp|^l03 im:;lGnJ'"TЪJhM|!z>q4Xgءqܱya2kr : V5p06(|C{Fe~ f$8zf(īT4LDIgW9ꕰ" %pRpvv:ͺF?qMQ0Ժ/줣r-6 UyAq!kPvն{cTͺ1ی "=MY(,Mpډa|L/WPP5Wلur(h#6i!y!}Kjb=XɇNHL* O}?Kpsp>M3a:HnӹLYo^1XPX8͕ W6Anîawf^@Kl |"" Ʃ3^NB! ٓrmK/r)[=>2[3QO ;]!h99mU|GXNΧ6kOG. h֏@gV׾ʚtx)H7>PIl_APlS%67GlLsQBkozwbqaoԽ %Sgrt6ua#-*0+ʜ JU|. |&&З͓Tgf>- '>ENb|L' F1+[n endstream endobj 9 0 obj 5106 endobj 10 0 obj << /Type /Page /Parent 478 0 R /Resources << /ColorSpace << /CS2 489 0 R /CS3 485 0 R >> /ExtGState << /GS2 507 0 R /GS3 508 0 R >> /Font << /TT7 496 0 R /C2_1 22 0 R /TT8 499 0 R /TT9 20 0 R /TT10 492 0 R /TT11 19 0 R /TT12 486 0 R /TT13 502 0 R >> /ProcSet [ /PDF /Text ] >> /Contents 11 0 R /MediaBox [ 0 0 595 842 ] /CropBox [ 0 0 595 842 ] /Rotate 0 /StructParents 4 >> endobj 11 0 obj << /Filter /FlateDecode /Length 12 0 R >> stream HWko8_] MjQHԋ6qtb+f2~.%cJnq{9xYoO/O :y\EN:^t(ORJcaR  Xw/=C D$D2P]oɴȊ2$u.QNN_brXhDq PKd-%82ցͅI ɛi2_^tU:-&L0Ī !T`8Be26 '^O Y >}&hpL36(lr?]Aqnm ׿ф44%'M#spw9rC@UU[UaֆbtMPZx[ [3i&cEYhXöNPn JFGƒٹ*Vc 9.e[.4-V *Jt5ofT$wl==ŷteX5tÎqP%gqYl4W8a8"Ьޕ^mUbCj YԺɣx+T< ʝkB5L6ξIIʶA¢ al\Ĺ}ڇNgN?6BJ*2F OhoHdf J )i-!aI/@[  IH{VhY<+u>]cd5L)k?8z!PS l^70R1/&:d5A_rKMZ{(`r|[e砀ʾ~P!@Gj4p@fwJecx?3XH+5LM} nK11a36JCv-|@ xg/v\rPt ؏9/g@>߭N^CrUc sek׈I20]J \m-^mNURzٻ!busE=&k{UT<@ż" ^ MYn=8 Р:٠muRn*4ԖLo#onY䫴nh8(R%;NPF6bC$@FÇ/u?D1Y[xHlݶ٪(ڋ?JBDVQNjrqY۴t/jnU^0J\&Kv.k1)w^Wq!ŢVaGM/ねkf)撎_!#Gsfb~sn~E_]ͧҲc Mn.>\RB)kMs99-|nNZrzH0 (+ xJC34 ++f8`^&]rGg(2}k%!/t}pXD:,Z9[N`0q8d)Y1+-AYvimn>K)7=Т$Q;}C@.nLm./+G o8\*AcتKϲy]d ;b$PdŜ9 P UcȢڙ"!! &X?zCr TwHc- etv?]0$ F}w.O j,U bԻrt\}M}sG&M3Yz5~c+J5hP $C}! .a{4 Cj~^=F~h=h /`l'F8Pm"uLV׋lpvnnngw )ADat$7r4C1a˓Fv*̈́~f0ჾ6t]/z9N=.P5yDHf{2z99"6Oı"V<4C1 K |-yaץ2^9ܛ Gi78 W8;A6z_iYbteh[%-v=UF.e0ɐ f@hla15tj G2\h5gXp7p=B>b*#`2V{ymP?,)m; 33\@t+ײDb_#ZynVƗKa$w ZWw]Ǣݛ_{Zt}d;\zDUFzhsazps R߬ooSka?\mQv }ELl%RGR3RJKJ2Cwvwvy~UTMtƦ#z:R^dy?|6x1hb+if.p4$ {w6A^4]Wηu*UZ/xK tn2[JzvVntylkL MӼJS:C)?kr^<>+NDo?IW{h$`=Jky5wum*Ci}KMeQ6'pw=6p ڪS(^C+ s]MZ 萜TlZl9'pt`IZ~){I1EM˼> {B"F{1:Rv\۝5@.~yd~~z7!hm+3K؋";Э?iT'/BӐijg^)lGY;`9٢2gB[rXiUzwT%`z(|$}ΤiL#Պ+/~S0 w첛,:\85E.a ΟIFqJ<ѶБa_^$#kR>: Qg7)@%H :aNDClGݸס8}]q8c1^ y`^"{IcAMM^yb9|S;剰bl _t=d*8޻-eZZ7D_A6L!|7ulEyhk9tY0htZ i/1rѰ?04=GwvJxd{8=# OQnw{m&ڢʥMQ6v<̍~,rEkW9i,",/M^<Գ˫NoE] ]h/L#j79|0|ap(&OZLf}44/(<`FVѤO(kZVq_ } W&}7n&4tFHK&7@>a o}hv> /ExtGState << /GS2 507 0 R /GS3 508 0 R >> /Font << /TT9 496 0 R /TT10 499 0 R /TT11 21 0 R /TT12 20 0 R /TT13 492 0 R /TT14 23 0 R /TT15 19 0 R /TT16 486 0 R /TT17 502 0 R >> /ProcSet [ /PDF /Text ] >> /Contents 14 0 R /MediaBox [ 0 0 595 842 ] /CropBox [ 0 0 595 842 ] /Rotate 0 /StructParents 5 >> endobj 14 0 obj << /Filter /FlateDecode /Length 15 0 R >> stream HW[oF~ׯPs'gQpbEfkE䁦F6T=#EbK̹9ۦ+vYޑ￿ټ=UuEnn.˟ܖq͛7*#h*Hj2?nusw/HFL?IW+N Օ峻˺)k4p]٬n6K8V1O&'IJy&QԤ NWܹޑwE֑o7~ڬZqe)ĚD)MÖ4n14~W&- ñX*R_)=~/WCq>`߽ob}.}1yBRP=1!n皢z qiAp%Fڬ؆KKԉ|U窬]TFj{!Y9$+MDȳdm[]Aϐ{Kڧ,IQdžEPEr \=Nt||Rz7VA328 n/%-*(:|-NRiwuִ~r_/E5˚d ^:|JoEfꊮtޕSE]= j /`` ELѵvM5؅Z[ O\ o*|Z'xvC]0Hu$ һ]':>}u`Io9k9ZԿ=e]xF܃fy(-2'qnMv#qKr4ñg`XoZYr\2C>  }uP8GFĿ kv_rh}-vdp5@gkn,XpJIhsqr^ P+fqbI}{P Xm$DbdvRfu~W raggk,yg0@ҙYπ@Y0PAM*d;nQk*زE?|/Ԙqp5KG@tG޽}9 _SI96+.vDy6jL?ָ#s',·? FE$FĻnam'p~QˬM[.xJQl#/N, r͆_4IbEȌ'K8!âP,5(VgduDLYׁ 9kdL7Ash;m`nnvCAV~lzTNS+(+ tDn:(:hnկIôX2-<ąoy103˳;e<pxj,RwӇJCلȝCQ)jb- > O@)iQw7a&7sLTs鶏=Yݸq,+ZFHZf1,:dJbBJv\R%RyPq" [CVVXxތ5 :H|󶆁;K gj^KDT]s['_nm X}ca??iLI 1~ y`EQ-Z<ṽuGT~ކ4cT{$e^JHߞ.i"n2(C9j2Q$( ;&h*[Zv`|Bea(0 6nJEըͿjG`zE'ƕ$̱O};-LK n+WU*J- 6{;1-N_SBb?]Ӟ?iam̛t7w.Tʕ.83`V Ѽ@>y ta3toh'7̊ T:n!IOL>E(GM*J{~D4/ț J?ٲnXhZDqZcCi,+uJ-vN.]ߎ͗VNTpNmo}.x)e 2 ν8IVav}4ǩ6x,Z'9Lh?Lva˕J8`{~[.ٔaЖ`T>> crHe.zӽA ˣT!7n-P xs46GĆ? 5o.P{zݶ"< =u+v$}5buP"֘~*2LKoiiJJv1jÖ/muj/-8U \wi*K;+~DnXʁ^]`>[D-jՏup , `ۆޕlDWOl߾\U*l μ}[]7$$Y%A6&vS!?"F Yp^֥ZZ]:Ȅh3s_i̻λFu2s=-PxHl.dFwe˚>fOnc[_ 2I$??}r*9&^?Oy$ {ՄnlwIP Z킴pa|켙y̳eλ?E7'(>[^^k,ws'hQn45A]C=t,C;7"tɽU#vk[Mīɘ zdh|6 , [Ƕe;&ǹv׉D\j/Ts^2 i j̼Y޴,6:iVbsOR9> m0'&s%vZP|O9 &qPIQ_UH&qQ '`@PG#ɁØp6a?JBS6PΔMڄG, Aͳ;u=mu* URw fPD%ĉ:_<&4S+(j&%S[%| M$=Q՚CN2;"Eo'+"_8~O{QG W j<2P- $F endstream endobj 15 0 obj 5959 endobj 16 0 obj << /Type /Page /Parent 478 0 R /Resources << /ColorSpace << /CS2 489 0 R /CS3 485 0 R >> /ExtGState << /GS2 507 0 R /GS3 508 0 R >> /Font << /TT6 496 0 R /TT7 499 0 R /TT8 20 0 R /TT9 19 0 R /TT10 486 0 R /TT11 502 0 R >> /ProcSet [ /PDF /Text ] >> /Contents 17 0 R /MediaBox [ 0 0 595 842 ] /CropBox [ 0 0 595 842 ] /Rotate 0 /StructParents 6 >> endobj 17 0 obj << /Filter /FlateDecode /Length 18 0 R >> stream HW[oF}ׯpqHE5Y$NZ<Ř"^~pFF"n64w=|X#?x9rA"N+ /||J>2&"ID2%J($ITO?jvyuIJhS?IW3F 2͔x\ek5ENbv .޷|#QR2ωK2F,[Yzݕz-y[j ~yv=}1E5Qi)(V0C*խu:MOr{u3Q‰}{o% 2ƱDeOzή!9l]λ|JfteHHϲL ^HJB?D/;Ӑ-3":դ[[)2}ەeQR9b1k]T-|,&QOS:<>ݣ|"Uȷw{$&G:Խ?o2}7O  ap{p&t|DeE~.vUc^7Ƭmx$*Y|d [@9d PTCvre&Xzpix{44HY^3D 8B\ zQ,H]1`t.X hnw}gV7[h ]N@ۏc]-kT#k{4ѕ֦)`"BSaXvC4V#)"% LWTb*F J#/<iQbXs X0Y46Eut x",b^7eAami2jH0բui4^FSP*^IS3q-a%/ %۷n~K>7oN';8I[՘mh\.ÌE,"T\>/KCe76PNA7>{?4 ;4c6P٥E= . .Bvѹ8$b̾E7bR [)I"ÓLF\eC̼pmΜ MDr>B]ɝ )O>: T |E@U@y>gZ"vzc 4R/JP-z߶Wš^LHYg"Exz.C2Q6̯sD@ىβr `DDÉjsέHB8N@}D_2cNޚ)aX s\7*mg9.|@2I?"l"DgЦ#yK\ZiX?TAgȒ gkX!24U:ϵoq@@%]Q=f]?'Ţw6 MS?SĠ4Z .9>+XЂN/UjMޯm(#);##l 6덶&o5!wʎC\@[3hD< 0U;fL_@ah\kE7Q^D^ޕgVYˆPA01 ЖAIh7d>7Пߵ~O)| bQ쮭#i IGD zE7Q I0*axr~ ޠ92_ MThYȏwkIi9nD%lJByƧUH]cwǢUd23l!A:S9T80z( ճ4gm'gBY v V1P93Mzd)j"Dxz75#Vr1-a -!Y_s`?PubJs at4) T<8y`80FS#("%˰"鹀d'+M rVAK]Dn\~9LaKe1t E lۄr֮'4.S`=a'[РbsP*eIhz[4Ač͢=*rй Q褣G[ɾ*Mۂ$IB- 0#%mq_y6>LO ,{m Vge#[G_>6̀| mFdv? RW-B߈РJ^z3K5K!2oooӮQ":XVK9|q ²ߥ`tflRE6 m7UxJnbFzYؘX ~ilr5IΥr֗}7e ʉKpˎ.僃/rWI䀺H@{<6 ñpzd='LB!!adlzsJREʩYpXl+ٶztd=3}HzTK&IL;$ aˠ4hɆa~|W[eYHխ k +oћgB^͗sƏ8n.AX>) zFZ=y`!PPp^a rb4IJ |7]d߽9z*}^?^P[_ZD`dL.#o+777u[G[QI4;y(CBWxGWHOIY(X4cUOLƧ.xBq(4R;IKA?Q ZYif`!sdUbT݉&dx]>^Z}@c$OB%JCZU+ g/q".v )>|I.T[QP0_WwK"ygmԠHIy!biʍ?ļHP7=#e_:EMHbu{_6wNRVN.m  K lPdyE$qL/ WGe-ͺuߗ ԂK1Q-NʐWq3@Dl`0b1d=QBbE7@N`S*2ACtλ^ˋ/ϋW?^^o]V[._bbq򬛏w/.~KxշƂ'Kd d(ꄭc'><3^8 [Eѕ˂ iiv%B;{6m󯆇Ǹ0]]v J[{}#jCt Zݖzb?D VQoz; ;ud![tF8Lq_߿ZCΒ̋cKR\ PM^Z6R_%,k|FCЌ?ZWB)HҠ eCĚ;07alJ^Xu19ZR4h+1&i;|W@NMDx24.$ll 9̡fkH&ģJFgeD3rs:ġq#Ɍ!_LD' >L o!~~(٧\tzZ^þJ1kRA_I}ca{vȸAX5gXDs} RZ;joi+iix֊Jk)uޱ Er&3{W͕dod8rD{QT1vNƨ7w|}9;1ZSd)/'SL3C5oazW"telymU 07# endstream endobj 18 0 obj 5101 endobj 19 0 obj << /Type /Font /Subtype /TrueType /FirstChar 32 /LastChar 32 /Widths [ 278 ] /Encoding /WinAnsiEncoding /BaseFont /CLPHJK+Arial /FontDescriptor 24 0 R >> endobj 20 0 obj << /Type /Font /Subtype /TrueType /FirstChar 32 /LastChar 32 /Widths [ 228 ] /Encoding /WinAnsiEncoding /BaseFont /CLPILG+ArialNarrow-Italic /FontDescriptor 26 0 R >> endobj 21 0 obj << /Type /Font /Subtype /TrueType /FirstChar 32 /LastChar 32 /Widths [ 228 ] /Encoding /WinAnsiEncoding /BaseFont /CLPJCF+ArialNarrow-BoldItalic /FontDescriptor 28 0 R >> endobj 22 0 obj << /Type /Font /Subtype /Type0 /BaseFont /CLPJKD+SymbolMT /Encoding /Identity-H /DescendantFonts [ 33 0 R ] /ToUnicode 34 0 R >> endobj 23 0 obj << /Type /Font /Subtype /TrueType /FirstChar 32 /LastChar 32 /Widths [ 250 ] /Encoding /WinAnsiEncoding /BaseFont /Times-BoldItalic /FontDescriptor 32 0 R >> endobj 24 0 obj << /Type /FontDescriptor /Ascent 905 /CapHeight 0 /Descent -211 /Flags 32 /FontBBox [ -665 -325 2000 1006 ] /FontName /CLPHJK+Arial /ItalicAngle 0 /StemV 0 /FontFile2 25 0 R >> endobj 25 0 obj << /Filter /FlateDecode /Length 7079 /Length1 20508 >> stream H\T xLg~?g&r)L3d"nɄ.!5#$*2[eǥQK֢zbÆeW[%V]OgU[5g3Բ=g~|H,9>IFa% @(ltmmک,96[أ\9isC@IX]d*f79`]jϊ}̓뀣2?(~+@Pj`鬯MTlcf6R-䁩+#?T#?IJ*.3Tm^)fЀox؇&AuX%a s~bk(lBwl|68>؏h^<,"tg B!j3PBpLFs܊m'ߪ_ -^zխ gW1rBf#gijC+pN沗-af*c?!©qz^f^7בt<4 Bc*w_ptzGԪj>g~ќv's|s0b//[8ON#IMԊMr*"8bOrTsױ3䢽"Z-N93o$*ޡTi}B_\1Nler窟F V`'nR<"UQ-i=tY 3⚬SAe0C2MY.V.<ánb<,_&lZp,.JQˠF sih5qtп`dt1U<+ֈF dg钽eZj\ŰGWJbr3յkjS}Wnc?mvLݡ&<: &}{R4AiMù3h"MYsEK59Ft- O 1EED(2Jd" 9]Ζk! ;D*JR(&rI-U_"m5Ŷfۿ۳"XK"|K,33\wr+ыp oN_EQG]Hm"k4fE;ξEubL1`QNQ%$=o:8[w^~y Is17D=: OP5x@mhFKuhc7ެds52x,1cKhE@G~9gh/Z|3CiQ">xJ V)J0\n~ݕ7z/q# +4B42ED2'a$`]=jP_d ߯oޏ٣鮴n]IMwvj:>!ّо]ۇĵlatӌTCfXg>Иjڃ994shӤ8- Y[׌yLc<ӽq5UaYz NۇBۿ;.xYs3a/ܡ5Oލ.!|ϒr_QUW{ T S2HV!$ &HKT*2$,چ4IЄ5 he4VGfw{o}a ?/{:s䚈S^H ~c߄UۖƔ R$2*Ze4IR,%/vIMd-rC1 Q11 ?CNQ)5JZ~WU`~:kl3cKg'_H`0htdRB͚pMx* (̜_yf1"5RbRT\?98hUtSٜˈvs4TW۔H Vg(u2w@]i贪yU+*ڧ.ԅϗԪe% i,PEV}jF"VHt*$u^GЖN t?>cJC#S"2|9-\Gy>rjpOjaa#F_;LoeRjRm] m2Izm[!h ,ʀIn- (am/HI)t^f`zEEE'%1{^-6shF菠~ tG!(o@,P6)@CuJقz0UcZ+m.8{Q~S!W< v1@:0S=IKx_nm`mPX6%sP} Q-"0 /vER'>^"ӟVZY%zbX+GILQ ֱWLcF|{2R) }2j7`_cOíTƾD?} .A۷fK`܇civ\cjAz/`2lE30\hRY`&&̫xEpl@l=!l1kO+gxt$m/scaa{}^'T{V 2[sf·jl5֚%seر^8oc،3 7>mJmճz6z/;!?FWW?u$| ѫ*z]o3I9vC9c13]gzQoÙf&8焧_4nVa$At_hE Ǐs}Pi5D(RO4R/R5HsǒN|; +6޶!NJ5">3ռx8 s;.,NŽ}|3H>qڻ9TmE92Uy}B8iǍ6j|k_)3Gk#Fa~O4PȚUFꡫqNb=BC)M{72F|(ňwIwY+:a/eP{-HQ,Hb%]#RMM[C(|(R rc:%:,:"fjxkx[zUȍT)}]lZ;b4R܃F?ƵEZr͓Na3De~ :p٬oS${akN'iy f`ZOm@ҷfr>Qvw| +rY`sNY2n9:c? u-d(کKu=}"T;I~w \.'9]nv3 c7=CSg8((KB q~'.%p}7G}`w_;)K2"L)?}R? idӭw}NVp rE{-{r^*ànMCeNPI9 8#n+ ځ5 ^C ~]~Y8tp x|ER[,sr5 ȝ\ !V`\;$^Oj%~stgQ WO]`"wD~nXej+p/GYp#ڿ~Y!?<}@9@ 02=2;Qƛe rC0;9 5u[b([~7ӛx}>a`"Dr-g~ey h)a.,@({)RgIlM::AƤiV^5sR2e֬@17Rvhݼ9@ϴy{|<ϙZ~},%OؿؿBϐy2׍;V7zAw!Ʌ9&?ȵMk%Y~%3,r//]Ӳs=sk۟ ԐI$ϲd`Z<]Z?Z5u?|o}ǴI?{'?{<7no >L~'޷7A zP FeN vg)yu_ס2>v'ow.mS=ϓ[?CS7$Ǫ+sm`pJww7"J PH>`'a, +POK5swH%|!aϯ7ttHR#S҄+ _bgi!Wf$xaFL mfF Ef 'F >0'/Yߦ0P8onnZ%07q @-h}`_ߛR pzůºʯkOU I#Xeji'?KZ;z:_&p4v_&?h`/ú i88 t`5r~>^Wh &䯤L_JH>M 7R_WR/|*Efp ]5 ԂFz6ՃJ6*OѻR8)S |D/Á?+D XBXB<K}l K@k;,!Ͱ Ww1ccc'ݲ0UY;.TsL{ivi]L;CL[ŴL 24L;ϖc(4]p!ƘviIVrYu8KRk*&@DWЏh Ð@Fza$KO.5+C{"k(.0JoQ<;}F)##\(P̫ɑy6&hy)SR$ wU Bk4&s5)^/R|^WxMɄSAs+KbyH&pIdld$7Kwimj*\!FISf *+ɫF3䷍Qiaaaaaaaaaaaaaaaaaaaaaaaa 'FK<`)eF g2̼c'}Vh6$3kӰ r)r4V:ӶbvO?ִf]<ybGTOQA-q RIiuWV'bʚnwf6D-#MU 1T{  \HCh4&!` zpȘ3<3 KmrHsU/zJ ;nktPl2;7 endstream endobj 26 0 obj << /Type /FontDescriptor /Ascent 935 /CapHeight 0 /Descent -211 /Flags 96 /FontBBox [ -214 -307 1000 1048 ] /FontName /CLPILG+ArialNarrow-Italic /ItalicAngle -15 /StemV 0 /FontFile2 27 0 R >> endobj 27 0 obj << /Filter /FlateDecode /Length 8642 /Length1 15052 >> stream HV TgrBr5A.a r5qLBLuM@I&dKT Zx(.}RxUtmuej=j[A };7???%kթGd:"q6J<!l7:`Jc̅lN8\g?2<[In" 73l 1M`X_ةbNMG40 5Ohp#@ю_!{)q$*;]+0dD/j֦տy=`#Hð\V6/]V5u8UDfHc@DA D*!V;:wZ8%#22aZNSބ RS%HsXhX`ј\*Fc蚌8,Z9XPܫ޲GJ*vrwmtNYu$:|ש;Fxz}sjgCk {m1LcF m Q8bnnNpfB69A+m-RNon9Ë<Wd~$XWw8cO\-XzzS֒NϒM#/+ī3ޛ淡{3BO]*~V Q%xyۢԚ~SeXSΨkѰmm{̪}ژ- #xMƑg2;:M},Xk;lCe Mgn)^$[{w3_(hRg)$0NJ11d|gĝ "58m˼P=r*V; Km=r Χ3aN%E7q5[Lܼ&|YL[[瘻cUGCK3,b&*h/DƤ ZJn]fD.Udt0dEB$cQ {Z4)&cnq,(HR Id(1(4 J(eރp9%T5xDL׵$MLrt,6ߏ<ٚgІdIFHn5A7ڬ9FJ8`L*x=WJMx E8w(<4xpHW"%r`b^=n4ל1>*2vk&YS{կv_hEGG?f4#4oy˥o9못Mߍt9Ѩ'@NWxoAFpqL\Α!= iugdݥ7yrnKKjmt%[ lkXmΚ˱n-VŞ &??cݵF oֽ%[s'>uT}{u1$cg|E᪩߱ ڞyP!L@,&)S[Z^˲c:~ט 0_!D#a3ك1F b1=6R᳹1iS7;5PWf5,Vqe͵} CN]sq0bht@+E\V3e+鸙!Ax,L&  DH&I+H%ڤhM6Td#l^o@y B, xUNzY R|VhBmf9*F ?v;`e/y1* jy3zXTj5}V# F 4 x\=hT{:jQ ~<@KxR)i9/,<)qZV1e8ǔe',ag2_$< 3#:HlΈJL7QI4>ǘq*$*IOyqy֜g8npFJ.21IDd)NRIx6{4K%'y-JbClpVPg7G#I_sz( 18*jYSIh ԹKJEXcw,0L +qxr҅U"'G-V&l'˼.kp-A&֟%;jy>WKR\4еn(=< Lґs1<2M*Y57Ur\5i0v2`.Mrپ0 8(˾$}z0]=;nǎtpFݑup9, YͿ֬=L~G&DAm > Ҭ&^&AYC-q2u\wqnL[08e!wW#˿V?ugs"!|0y7~gߛJ#~fV8}kˆ ~Z4>Zx–K]kJtJqɣفbW/?΋YSKc!P:@UHіPb '}_> X(.\]eKT⛊CZ}CsWX7An!uTYO%xp)zev|x\sql^z44=3+D㾙 \RɕQ3#Y{G窼N4z]yu٢6ю=ۏyr1<'Nʈ{șpfCuEk.H:`bn< L :rԎQJŔ j@oܵH_@(mam#?p&e,ܡ Mipcۮ7<4f=ο;a3n~PX'6.|뉵ckh! > _|nphհ kђ!z `] 0(i r\ːa8'qFܝw}ZP @&c1g@ f/\!tƝ{DgEHv0IDhA6h{ #X!U~)F)pꠍ8d ERHb")dCI|Ggf1SȎj\pRAJb`4R%J  XӐ"X6BZv,Ai W MK܈L$~@I YN֑d?9LN[Hw#Fm+U7zޥ- eɌdZ?g69ms'rAq[1A/ ) s1B"ۀ^.靰iz hF1(釖u#HSjd@&tA<br%9I.jrԓ&bR4Π3i&j  zi5^ez3};Q5˜p$U>e։Ul.`kz817 6hhH/Zkظh,E}_{H;NSD>s&$"- M4Ofs\ܞXGAM/7D[GűxOOB*!ca{i`]]3K]i=6Ne oȹV Nu puOu"pCr$GG}CWؤ6_GZ+kZBTKq*dcnhr)un5"c:a=6kSQYq^X;OǁZJv5uSyj[O߃}c~ݿ g O\r:kr,hX9ݴTm-zx/ܖ&塇ut? ;x R }W-^k|ԝ`ҦqTmc2e6~`9PST|tk6N*Kō;^IGuvg`+:NLqʱ~ܛFEr_ ZMB <' GݺgĻ|\e{p~ ]ɟ CJ4n?cc_]uڙqېgIߡ=',dl>ٹcccV[;KAx ]q-ú1vu#8fRTS2v{rL)^>aߝc+E98mU&/,[_lizc\M]iE;@/p)jQR vM 3i89lߧQq.ӛڸ6ߴʨ5SA}ܲөP O!ãx^v9n;5?Q_G!3 *| S?Zٽ=E=JQzCF@;=17=R4)dLqs'sBW!&s7p}j44t|PקT|w2r{ {*Oa5k$9ڢtzwBmrrJ6V&´Ѯ>zI?˩Y4Jԭ_tqyjkșg!D>}SE&/{/q98~#'(5~'쾀{SQ:{ohz:e@y׏P?Ǵ*U֘cy!Gh#S܉XCNickg5Gh/̾N}KN},8fwc:F>Y.ݯ%*{^;d ֭tΧy>ܽ?rF(( ؖpZЅ›UmSl78(EE],)^l," -n cgn Q<;n[qOx rE\4ir|.5㾽ר4N6""c1%CP6eBFCMI=gu.:-%&Id9]ΖL(bTX2ec\&fh1Vtr:=24-Ni" 0 aZ 4%ոfh4'x6eF8K[jRMYjϨJjIٗ{>xrmұ,V77m !si)/^Hסr͘b.)GN+05T@իs5rg=2مD@bG>/ џކ֭w1_ㆽ='.j?+ΈK_(ϙ|D:5詜ʂ}VJc^R^a2k$ZgaP o&GQ+%?.ɝk*v@&A?ݑ,DDhDP [ *Ek6K z輻rP| ~R]iܳ/ԭ3}N Ӝ4Y}xN+Hg>.8Ȯ/"abLmCA6)KK}`z^H]"0Ho*;XRg12Cw:} w }I_=RkOdʉy?"Di<0?͔LMj%Ј꠾AjVG KzG dz{~DQtlB j{pܰxo° 7-#U.@כSAnUX\`UxoŬ3:2׫!j&3sECbFb=Zw 4+F"}GL Hd>fkj n |<6>@XtL5qNV6O:\`ᦖ`~s5]l@.]luv %] O>t%讯::Rt/Ƕ4] Zȉx_g@k0EI:̨=+'zsk0k=-noΎ[|U9r`:gACr?w;Yj+8Rw;:] p.`n\CKç[Z!˒O}2}pUs4W*պxYCP9xJkRRT̑<UmC[5͡>[׺w휚=20:5GGL ;a^)Q8XOa@A81 Q;vHmah:a(8;nkO~/u܁&ޚ31gڙ0w;aS?C endstream endobj 28 0 obj << /Type /FontDescriptor /Ascent 935 /CapHeight 0 /Descent -211 /Flags 96 /FontBBox [ -204 -307 1000 1107 ] /FontName /CLPJCF+ArialNarrow-BoldItalic /ItalicAngle -15 /StemV 133 /FontFile2 29 0 R >> endobj 29 0 obj << /Filter /FlateDecode /Length 8694 /Length1 15184 >> stream HV PSgrBr5 krIB&A{\EEjixRQ[oף(t@E*RՊ7~VQ[wgvfwvޠ0$:uY@m3EQ47L/1HAfZfwO_1%љ }䙣֜65v;>hn٬ʦq)K59ʼn8 _Ag~$WʏXO^+Zzfc疒.V#.~ǫ>ⷾqntOXA߻"38>(<V3lIKLʰ\/p0טxQtiP'9C|Z1t!Vd䪚ۂEE2 sxyX|Du?InK)҄)o-kUxq$\wۯe+Y-zFgooM{^Ԁ翌 +Qs0I_^Ta.`G.Ydp0hfE@$chI (IF2$M!IƒąȐ@b&WI2SCp9X\kq6hlTY%B IPi50br9`H ơ|zF(“ϝ` ̨H]y# ϱ99! +Fs9 r`zi^=n 4Ԝ!o7=RE#,Uf4i_ek{wGq^~ c'K5OxY Ky![GB٬]Yu[RkώJ'Kosd]D՚xڧ틟fmXF@]aG2gl;U:y߰|g\ 7ܒ-Mt*'}SoNksŔCRlK@sfg0Iƣ^}LUUTQYQ*-ᄲۼ^Q{|$D\dhnƞ 7AkЄHKd qhmpp A=ZHH鲘Hk (0NM$$"Hq~~tL$5h"qn'$`DM h@qtx *† =vp8Ac^sH9ALh@RQ#FN*/By4(e3Ԑ1Pa,J@"d`GdafxYA"&j@$ѲT IZQ( J#j|E#(wό"2UkkT}NN}F^ B~rPt8B xYXhZXt9B+>gkZ-ߍ SGn@@|BP<e| } S4|p&X2MP*y:b$dVi!aB&*E"MjDeAir;-8q 9j)i?=d\27cZFZb6, wFt:n ho"wFTbz?N YG1z5 5IO}u$Ӟxuܠ2BnOͻz$w1lfI$Gd9;??3Ba au1H7T.h+JBOjtolBI& Q|b?.T$=2\"l^M Waip9]UV@҅5Dt{2aټ'|4)ZhM+,qMiJԶ /΅Ko4 phkL#1Y 'l\#/pMc'׼xlK l]?8?r 8(˭ؿRF`af)uHvRk6S\2ǟHmP$esƃ R! xPaOm*։O H3i$@ =q625ᒺ.>&ƥǥey#bm+؏?4xvCDs鸡Oh&Nþ:wg܋Î 䦴+d# vfiァWǿ>yTP>>1+v͙ }z$#pnNJy;*iĶ%t (ueW=_w*;6d7w}#-NJUΕs ^~4F}eQY6ݛm^%/9TAhsLzr7.ѯũ#`F޲E.f"\|bFoz8i?O_OOo//M厢\Cr7rs̼>lۚ4_RCatOud ^>wOE\֭tm'7L╴w%c2}[U' \Ң<y҅>c, Uj UqܟW9!ujmL|Z`uaSKQksZDR ХУUjpr !"(vՀ @h]c9WcLnf;V; VE3 Qho->>x{p×pa(K, @;>K6` [¯h Bpihj;dU``A4`^ʀ `H!.`E8CajJqȄP5pѷQx}0W HKhBo,p{yOGxwLL1fsU3 a&jB TP у^;. j#dphwȁBĿvA[hwB$ܦfԍLe"|f-# r88}:h!1&b4"Eo v;N&-#OK%nć,&+H)9EKze0-L K؈fa0Fv:Hp48w(=F:U #r#r7߇ "D@"H !d59J>Gjt E32vYren8vpFwv,HW+[Z(\f!"\YG!}ME|>gf̜99w_" g{mmD"۪SSҢ>| J/kU֥>.SG#eu@(WT'5l3V(_U+iРrJz!R{rSuQ#v}a gXmD^V[jIՒŋV~!yY\Pטys=sgϚ9`;Լܜ).CMa37xIk%f}_6ts]6܈K3ceݓ,)@֒ZaLcoB?2c-GT4^0³{Bgq##;zp<9A3ؕ/DN.\h\f{{Թ_gΜ >]¿Hw|;su8=-iCqJ[:qȾ?wN_')Wϩwc:%zҾlNsh 'XHvwrv`POd$bp8}:!ׁqs 1Ί6C?lݏ3;W>2.^3‡ $qO'DR`w\ 1 7?72yW=}o7aE_~e ?k[ EJ0.|[Yw'/r<- JQw+i!UފcFcD+d;%E߮.-ԭ ڏW#PIg.0$yTd[whXr]$ВZklXM%xIOڶDG^wyCπ{,p 4z' lmFoFFnFazc(ٽ]o_ꎳov8rĵ1tċ}w#!hR*MDJIUsbPZ5բ"OpˇJ4BڒJ77fvYNHP> ͨ:j7}Zo٥pP<:.w1J *\"l,Ĕ MB Ng )xҬ-9b* ʢ,+R!1IjvJIIj9$='HoIIE {56ڭRKN=ꂺ.˪b1FwiER`TB~:_6em> >*?'9/m^ ^NVh[^E׾ IUb*c<I|3j('GSPpԌ.F]6iN*+,{\ `NX9ztlGDGc6MʐدWmqw1A[~~V;*?"4ka,Hy1:YTMdeweg.@}nŭpV rdSow*$J71)urHO*R r,nYKt \-ף*s8I #3d~[o81+5n^Nnj}!IMy{l(ض&>Z|!ItgID}V|<;`&i^A&0 1Pu4Q$ )Z©d2a:Ϋy=`p=>sx.*߁>Wgx2 o<;kxs+ΎtX+g J!'✹wSȘK0#ÃN; "e"el"D.PR\UyL o ;-+չsiˢ+%)L!")sd{`NxUj@m2y,Sm91zCzxb|B;xk0`a&Q&an> endobj 31 0 obj << /Filter /FlateDecode /Length 6571 /Length1 10232 >> stream HW TSg~YlMPۡEe90 uLƒ ؁ ,atçP>#t|#O%.3 ׽w t./`3\ vMGEf7#q=wb@HĆK(xgYͼqkWC]F8BBAyE7j%;nIY&M' 6T:}`2q!r@#)©ct0G>`VD*Bz5 4b'9@; #6%FUi '`)v2+t2QFCG}=G2i:(FK#"?pnx r.^t:p4[$8wqwzNik?CGt͔?4lWU[st>Y_u= Mdw :SAgO9\!uͻAk76NH^5aK.uLLWRy_{fIgmu]G\H?-d|f3lUS+l9osn=mH_"(buPY>8o3QL?+ߵw;t˛*B %qt8k8);(z nwJ+NΪ_btJ4/H;+6Tp->I:Ŭy^UYSn?2*jWۆzNΑhZKO{8K1^7 1[u[?Lta2XЖk~"{!8 Lwb>~Ժ\{Ï/_Sycqoc=v^X|oYGH&;gɟtfLCb!-i\mfعOVI޹fܞ$E][f1LOavuֽ7U x@L_9G(As T҂7IO`Q6= 75eY?=W@6GپukWD;` m-C-E4[XndfKD3ʺ7*o4Bp}O|# ]w̐5 \Q=-o65m[\w 8ͫb!;_qݥJ<Żz2b;Vvfm|(4c=Т~1oODZ-9Erġ[r޽Q-?gㅅuټv;J?81Nں+&iXRwŹ8{DOz,&u,AU۴1'?]Brq  n%6\C]bա%Me'cFt&FAلQO):p;p5  H#I9#e.yM(]^z#E7Dؚ(܂[)02 A$ JP$_O3ekz*Ҭb 4qz;t&T=NmDإǝ)<:)iOړkD.CBY\` 9GZ.s? 3ĊӅ,Hp*IC:c?o+a<1EJhgcM-:fL=/if4n ]?8?M38@wa{1ه =FSYcG:W SMn_YsƁǤ^L ;"u( "!!$ dlm4 wMMO4ą&MK#ѠqeL孓#VLl w i>x2ܚFG.:^EމsE]BÏxnVU_=fOC3=4O43J܌buZx(W>ؒ֜Y\?z^{S hˡK36ݷ,1ꩀoV\-0WZKiVd15.tU|; Ie#lȻ}/=m 'M6Ѣ$\Ʈ"Y9C'A)V_;-NSFGCtćq0}i?=dR֐ʦM_´+/w}uۅ;TyҺHiI?޻P-ϯ)^U=Kn *D>t |&:UPnYQ(r}ΧRUS6>yK$]3o_Lw٦evc3uc&2wqFY~'$d乊T&mR}]Ni2Ji!=AOD̙E̟-gl}bVNr8/.r\#̵RކBS|hD4Utu;u554BTCd $c.i I.sl|6O:,bAd FB?flM|Q0/ .~%E,&ݴV@6]. PRZ3:;AQKZsԀdtA3z 67-ÚAt<:5;sRjĔw5V(#WQ8C:`ɜ'{ zc8ޝ.v8&8NL3&䟗c_H1x Nj; Kж 01FVtD*jڤjC:Tt˷}'LZvZMℤC>Nٿ>w{7xU1}`kޞ;wvlkjZ[o﹦MO{cWa%& u(` Aux8d5E*Z߇*i=|S_IJ¡6PqLUh 1T=gBPC1 о\G!8!Op."];|i -مQQ$ېP>-]/P~;a~\ӓDrX2 GywEs~BXoJwɏV  t׍BkJړ(8N݊@6B9-yc]#+hEwAr `qs,J.q:;4e@w]KThQ%aSd#f 7>/[׭vjY˵Ϸ|En7 ٢;n5:]p3on^nB|{3{ю82|7<7f ]v,jeHnź|^I+R[R~BCI]R~פ|@od씫J.˲( 2'\W,5׉NFD;9ֲ98On-^JiȡT9{H`,U$%]{)͞i8]xVjEeS u!>6πg(&]nG[{GN^9>ȫW$;&Qy[ZOO&v2d+k)vH$"Mϝ3YE)`:;>hf^S'cTWcJ!rSQc8e |Dj&f.@d sx%쿏X$Y6d+{F9fNs,VDc:9H# &n>98Uit;[Pr W⹮ LH(L`&k}~RDu:q++1cLJܙyS3>ñ-1Iӟqلqm I' t{~xp08 amZm\H6'8.w}/O4V UٰZSwc;vmts,{.qed펝g?g`*6k>8pB;ݳXf}&@n-/1:J'gEI_G endstream endobj 32 0 obj << /Type /FontDescriptor /Ascent 911 /CapHeight 669 /Descent -223 /Flags 262242 /FontBBox [ -200 -218 996 921 ] /FontName /Times-BoldItalic /ItalicAngle -15 /StemV 133 /XHeight 462 /StemH 121 >> endobj 33 0 obj << /Type /Font /Subtype /CIDFontType2 /BaseFont /CLPJKD+SymbolMT /FontDescriptor 30 0 R /CIDSystemInfo << /Registry (Adobe)/Ordering (Identity)/Supplement 0 >> /DW 1000 /W [ 3 [ 250 ] 120 [ 459 ] ] >> endobj 34 0 obj << /Filter /FlateDecode /Length 229 >> stream HTn > endobj 36 0 obj << /Title (FREE SOFTWARE LICENSING AGREEMENT CeCILL) /Dest [ 482 0 R /XYZ 0 687 null ] /Parent 35 0 R /Next 37 0 R /First 38 0 R /Last 39 0 R /Count 5 >> endobj 37 0 obj << /Title (10.1. In the event of a breach by the Licensee of its obligations hereun\ der, the Licensor may automatically terminate this Agreement thirty \(30\ \) days after notice has been sent to the Licensee and has remained inef\ fective.) /Dest [ 13 0 R /XYZ 0 -594 null ] /Parent 35 0 R /Prev 36 0 R >> endobj 38 0 obj << /Title (\376\377\0003\000.\0001\000.\000\240\000T\000h\000e\000 \000L\000i\000c\000\ e\000n\000s\000e\000e\000 \000s\000h\000a\000l\000l\000 \000b\000e\000 \000\ d\000e\000e\000m\000e\000d\000 \000a\000s\000 \000h\000a\000v\000i\000n\000\ g\000 \000a\000c\000c\000e\000) /Dest [ 4 0 R /XYZ 0 308 null ] /Parent 36 0 R /Next 42 0 R >> endobj 39 0 obj << /Title (\376\377\0009\000.\0003\000.\000 \000T\000h\000e\000 \000L\000i\000c\000\ e\000n\000s\000e\000e\000 \000a\000c\000k\000n\000o\000w\000l\000e\000d\000\ g\000e\000s\000 \000t\000h\000a\000t\000 \000t\000h\000e\000 \000S\000o\000\ f\000t\000w\000a\000r\000e\000 ) /Dest [ 13 0 R /XYZ 0 566 null ] /Parent 36 0 R /Prev 40 0 R >> endobj 40 0 obj << /Title (\376\377\0009\000.\0001\000.\000\240\000T\000h\000e\000 \000L\000i\000c\000\ e\000n\000s\000e\000e\000 \000a\000c\000k\000n\000o\000w\000l\000e\000d\000\ g\000e\000s\000 \000t\000h\000a\000t\000 \000t\000h\000e\000 \000c\000u\000\ r\000r\000e\000n\000t\000 \000) /Dest [ 13 0 R /XYZ 0 158 null ] /Parent 36 0 R /Prev 41 0 R /Next 39 0 R >> endobj 41 0 obj << /Title (\376\377\0008\000.\0002\000.\000\240\000T\000h\000e\000 \000L\000i\000c\000\ e\000n\000s\000o\000r \031\000s\000 \000l\000i\000a\000b\000i\000l\000i\000\ t\000y\000 \000i\000s\000 \000l\000i\000m\000i\000t\000e\000d\000 \000t\000\ o\000 \000t\000h\000e\000 \000) /Dest [ 13 0 R /XYZ 0 439 null ] /Parent 36 0 R /Prev 42 0 R /Next 40 0 R >> endobj 42 0 obj << /Title (\376\377\0007\000.\0001\000.\000\240\000U\000n\000d\000e\000r\000 \000n\000\ o\000 \000c\000i\000r\000c\000u\000m\000s\000t\000a\000n\000c\000e\000s\000\ \000s\000h\000a\000l\000l\000 \000t\000h\000e\000 \000A\000g\000r\000e\000\ e\000m\000e\000n\000t\000 \000) /Dest [ 10 0 R /XYZ 0 159 null ] /Parent 36 0 R /Prev 38 0 R /Next 41 0 R >> endobj 43 0 obj << /S /Normal /C /Normal /Pg 482 0 R /K 0 /P 429 0 R >> endobj 44 0 obj << /Normal /P /Titre#20turquoise#20Contrat /P /sous-titre#201 /P /Style#20sous-titre#201#20+#20Gauche#C2#A0:#20#200#20cm /P /Body#20Text#202 /P /Retrait#20corps#20de#20texte /P /Texte /P /Corps#20de#20texte /P /sous-titre#20chiffre#203 /P /sous-titre#202 /P /Texte#20Car /P /Body#20Text#20Indent#202 /P /Titre#202 /H2 /Corps#20de#20texte#202 /P /En-t#C3#AAte /P /Titre#201 /H1 /Note#20de#20bas#20de#20page /P /Titre#203 /H3 /TextBox /Div /Frame /Div /Footnote /Note /Endnote /Note /Shape /Figure /InlineShape /Figure /TOA /TOC /TOAI /TOCI /TOF /TOC /TOFI /TOCI /Superscript /Span /Subscript /Span /Strikeout /Span /Underline /Span /DropCap /Figure >> endobj 45 0 obj << /Normal 46 0 R /Titre#20turquoise#20Contrat 50 0 R /sous-titre#201 52 0 R /Style#20sous-titre#201#20+#20Gauche#C2#A0:#20#200#20cm 58 0 R /Body#20Text#202 60 0 R /Retrait#20corps#20de#20texte 65 0 R /Texte 90 0 R /Corps#20de#20texte 93 0 R /sous-titre#20chiffre#203 96 0 R /sous-titre#202 111 0 R /Texte#20Car 114 0 R /Body#20Text#20Indent#202 168 0 R /Titre#202 180 0 R /Corps#20de#20texte#202 259 0 R /En-t#C3#AAte 321 0 R /Titre#201 369 0 R /Note#20de#20bas#20de#20page 427 0 R /Titre#203 428 0 R >> endobj 46 0 obj << /O /Layout /WritingMode /LrTb /StartIndent 0 /EndIndent 0 /TextAlign /Start /SpaceBefore 0 /SpaceAfter 0 /TextIndent 0 >> endobj 47 0 obj << /S /Normal /C /Normal /Pg 482 0 R /K 1 /P 429 0 R >> endobj 48 0 obj << /S /Titre#20turquoise#20Contrat /C /Titre#20turquoise#20Contrat /Pg 482 0 R /K 2 /P 429 0 R >> endobj 49 0 obj << /S /sous-titre#201 /C /sous-titre#201 /Pg 482 0 R /K 3 /P 429 0 R >> endobj 50 0 obj << /O /Layout /WritingMode /LrTb /StartIndent 0 /EndIndent 0 /TextAlign /Start /SpaceBefore 0 /SpaceAfter 0 /TextIndent 0 >> endobj 51 0 obj << /S /sous-titre#201 /C /sous-titre#201 /Pg 482 0 R /K 4 /P 429 0 R >> endobj 52 0 obj << /O /Layout /WritingMode /LrTb /StartIndent 5.64999 /EndIndent 0 /TextAlign /Start /SpaceBefore 0 /SpaceAfter 0 /TextIndent 0 >> endobj 53 0 obj << /S /sous-titre#201 /C /sous-titre#201 /Pg 482 0 R /K 5 /P 429 0 R >> endobj 54 0 obj << /S /sous-titre#201 /C /sous-titre#201 /Pg 482 0 R /K 6 /P 429 0 R >> endobj 55 0 obj << /S /sous-titre#201 /C /sous-titre#201 /Pg 482 0 R /K 7 /P 429 0 R >> endobj 56 0 obj << /S /Style#20sous-titre#201#20+#20Gauche#C2#A0:#20#200#20cm /C /Style#20sous-titre#201#20+#20Gauche#C2#A0:#20#200#20cm /Pg 482 0 R /K 8 /P 429 0 R >> endobj 57 0 obj << /S /Body#20Text#202 /A [ 59 0 R ] /C /Body#20Text#202 /Pg 482 0 R /K 9 /P 429 0 R >> endobj 58 0 obj << /O /Layout /WritingMode /LrTb /StartIndent 8.5 /EndIndent 0 /TextAlign /Start /SpaceBefore 0 /SpaceAfter 0 /TextIndent 0 >> endobj 59 0 obj << /O /Layout /SpaceAfter 6 >> endobj 60 0 obj << /O /Layout /WritingMode /LrTb /StartIndent 0 /EndIndent 0 /TextAlign /Justify /SpaceBefore 0 /SpaceAfter 0 /TextIndent 0 >> endobj 61 0 obj << /S /Body#20Text#202 /A [ 62 0 R ] /C /Body#20Text#202 /Pg 482 0 R /K 10 /P 429 0 R >> endobj 62 0 obj << /O /Layout /StartIndent 36 /SpaceAfter 6 /TextIndent -17.99998 >> endobj 63 0 obj << /S /Retrait#20corps#20de#20texte /C /Retrait#20corps#20de#20texte /Pg 482 0 R /K 11 /P 429 0 R >> endobj 64 0 obj << /S /Body#20Text#202 /A [ 66 0 R ] /C /Body#20Text#202 /Pg 482 0 R /K 12 /P 429 0 R >> endobj 65 0 obj << /O /Layout /WritingMode /LrTb /StartIndent 35.45 /EndIndent 0 /TextAlign /Justify /SpaceBefore 0 /SpaceAfter 0 /TextIndent -17.44998 >> endobj 66 0 obj << /O /Layout /SpaceAfter 6 >> endobj 67 0 obj << /S /Body#20Text#202 /A [ 68 0 R ] /C /Body#20Text#202 /Pg 482 0 R /K [ 13 69 0 R 15 ] /P 429 0 R >> endobj 68 0 obj << /O /Layout /SpaceAfter 6 >> endobj 69 0 obj << /S /Superscript /P 67 0 R /A 449 0 R /Pg 482 0 R /K 14 >> endobj 70 0 obj << /S /Body#20Text#202 /A [ 71 0 R ] /C /Body#20Text#202 /Pg 482 0 R /K 16 /P 429 0 R >> endobj 71 0 obj << /O /Layout /SpaceAfter 6 >> endobj 72 0 obj << /S /Body#20Text#202 /A [ 73 0 R ] /C /Body#20Text#202 /Pg 482 0 R /K 17 /P 429 0 R >> endobj 73 0 obj << /O /Layout /SpaceAfter 6 >> endobj 74 0 obj << /S /Body#20Text#202 /A [ 75 0 R ] /C /Body#20Text#202 /Pg 482 0 R /K 18 /P 429 0 R >> endobj 75 0 obj << /O /Layout /SpaceAfter 6 >> endobj 76 0 obj << /S /sous-titre#201 /A [ 77 0 R ] /C /sous-titre#201 /Pg 482 0 R /K 19 /P 429 0 R >> endobj 77 0 obj << /O /Layout /StartIndent 0 /TextAlign /Justify /SpaceAfter 6 >> endobj 78 0 obj << /S /Body#20Text#202 /A [ 79 0 R ] /C /Body#20Text#202 /Pg 482 0 R /K 20 /P 429 0 R >> endobj 79 0 obj << /O /Layout /SpaceAfter 6 >> endobj 80 0 obj << /S /Body#20Text#202 /A [ 81 0 R ] /C /Body#20Text#202 /Pg 482 0 R /K 21 /P 429 0 R >> endobj 81 0 obj << /O /Layout /SpaceAfter 6 >> endobj 82 0 obj << /S /Body#20Text#202 /A [ 83 0 R ] /C /Body#20Text#202 /Pg 482 0 R /K 22 /P 429 0 R >> endobj 83 0 obj << /O /Layout /SpaceAfter 6 >> endobj 84 0 obj << /S /Body#20Text#202 /A [ 85 0 R ] /C /Body#20Text#202 /Pg 482 0 R /K 23 /P 429 0 R >> endobj 85 0 obj << /O /Layout /SpaceAfter 6 >> endobj 86 0 obj << /S /Body#20Text#202 /A [ 87 0 R ] /C /Body#20Text#202 /Pg 482 0 R /K 24 /P 429 0 R >> endobj 87 0 obj << /O /Layout /SpaceAfter 6 >> endobj 88 0 obj << /S /Texte /C /Texte /Pg 482 0 R /K 25 /P 429 0 R >> endobj 89 0 obj << /S /sous-titre#201 /C /sous-titre#201 /Pg 1 0 R /K 0 /P 429 0 R >> endobj 90 0 obj << /O /Layout /WritingMode /LrTb /StartIndent 0 /EndIndent 0 /TextAlign /Justify /SpaceBefore 0 /SpaceAfter 0 /TextIndent 0 >> endobj 91 0 obj << /S /Corps#20de#20texte /C /Corps#20de#20texte /Pg 1 0 R /K 1 /P 429 0 R >> endobj 92 0 obj << /S /Corps#20de#20texte /C /Corps#20de#20texte /Pg 1 0 R /K 2 /P 429 0 R >> endobj 93 0 obj << /O /Layout /WritingMode /LrTb /StartIndent 0 /EndIndent 0 /TextAlign /Start /SpaceBefore 0 /SpaceAfter 0 /TextIndent 0 >> endobj 94 0 obj << /S /sous-titre#20chiffre#203 /A [ 95 0 R ] /C /sous-titre#20chiffre#203 /Pg 1 0 R /K 3 /P 429 0 R >> endobj 95 0 obj << /O /Layout /TextAlign /Justify >> endobj 96 0 obj << /O /Layout /WritingMode /LrTb /StartIndent 0 /EndIndent 0 /TextAlign /Start /SpaceBefore 0 /SpaceAfter 0 /TextIndent 0 >> endobj 97 0 obj << /S /sous-titre#20chiffre#203 /A [ 98 0 R ] /C /sous-titre#20chiffre#203 /Pg 1 0 R /K 4 /P 429 0 R >> endobj 98 0 obj << /O /Layout /TextAlign /Justify >> endobj 99 0 obj << /S /sous-titre#20chiffre#203 /A [ 100 0 R ] /C /sous-titre#20chiffre#203 /Pg 1 0 R /K 5 /P 429 0 R >> endobj 100 0 obj << /O /Layout /TextAlign /Justify >> endobj 101 0 obj << /S /sous-titre#20chiffre#203 /A [ 102 0 R ] /C /sous-titre#20chiffre#203 /Pg 1 0 R /K 6 /P 429 0 R >> endobj 102 0 obj << /O /Layout /TextAlign /Justify >> endobj 103 0 obj << /S /Texte /C /Texte /Pg 1 0 R /K 7 /P 429 0 R >> endobj 104 0 obj << /S /Texte /C /Texte /Pg 1 0 R /K 8 /P 429 0 R >> endobj 105 0 obj << /S /Body#20Text#202 /A [ 106 0 R ] /C /Body#20Text#202 /Pg 1 0 R /K 9 /P 429 0 R >> endobj 106 0 obj << /O /Layout /SpaceAfter 6 >> endobj 107 0 obj << /S /Texte /C /Texte /Pg 1 0 R /K 10 /P 429 0 R >> endobj 108 0 obj << /S /Texte /C /Texte /Pg 1 0 R /K 11 /P 429 0 R >> endobj 109 0 obj << /S /sous-titre#201 /C /sous-titre#201 /Pg 4 0 R /K 0 /P 429 0 R >> endobj 110 0 obj << /S /sous-titre#202 /C /sous-titre#202 /Pg 4 0 R /K 1 /P 430 0 R >> endobj 111 0 obj << /O /Layout /WritingMode /LrTb /StartIndent 0 /EndIndent 0 /TextAlign /Start /SpaceBefore 0 /SpaceAfter 0 /TextIndent 0 >> endobj 112 0 obj << /S /Texte#20Car /C /Texte#20Car /Pg 4 0 R /K 2 /P 430 0 R >> endobj 113 0 obj << /S /Texte /C /Texte /Pg 4 0 R /K 3 /P 430 0 R >> endobj 114 0 obj << /O /Layout /WritingMode /LrTb /StartIndent 0 /EndIndent 0 /TextAlign /Justify /SpaceBefore 0 /SpaceAfter 0 /TextIndent 0 >> endobj 115 0 obj << /S /Texte /C /Texte /Pg 4 0 R /K 4 /P 430 0 R >> endobj 116 0 obj << /S /Texte /C /Texte /Pg 4 0 R /K [ 117 0 R 6 ] /P 430 0 R >> endobj 117 0 obj << /S /Underline /P 116 0 R /A 454 0 R /Pg 4 0 R /K 5 >> endobj 118 0 obj << /S /Texte /C /Texte /Pg 4 0 R /K 7 /P 430 0 R >> endobj 119 0 obj << /S /Texte /C /Texte /Pg 4 0 R /K [ 120 0 R 9 ] /P 430 0 R >> endobj 120 0 obj << /S /Underline /P 119 0 R /A 455 0 R /Pg 4 0 R /K 8 >> endobj 121 0 obj << /S /Texte /C /Texte /Pg 4 0 R /K 10 /P 430 0 R >> endobj 122 0 obj << /S /Texte /C /Texte /Pg 4 0 R /K [ 123 0 R 12 ] /P 430 0 R >> endobj 123 0 obj << /S /Underline /P 122 0 R /A 456 0 R /Pg 4 0 R /K 11 >> endobj 124 0 obj << /S /Texte /C /Texte /Pg 4 0 R /K 13 /P 430 0 R >> endobj 125 0 obj << /S /Texte /C /Texte /Pg 4 0 R /K [ 126 0 R 15 ] /P 430 0 R >> endobj 126 0 obj << /S /Underline /P 125 0 R /A 457 0 R /Pg 4 0 R /K 14 >> endobj 127 0 obj << /S /Texte /C /Texte /Pg 4 0 R /K 16 /P 430 0 R >> endobj 128 0 obj << /S /Texte /C /Texte /Pg 4 0 R /K [ 129 0 R 18 ] /P 430 0 R >> endobj 129 0 obj << /S /Underline /P 128 0 R /A 458 0 R /Pg 4 0 R /K 17 >> endobj 130 0 obj << /S /Texte /C /Texte /Pg 4 0 R /K 19 /P 430 0 R >> endobj 131 0 obj << /S /Texte /C /Texte /Pg 4 0 R /K [ 132 0 R 21 ] /P 430 0 R >> endobj 132 0 obj << /S /Underline /P 131 0 R /A 459 0 R /Pg 4 0 R /K 20 >> endobj 133 0 obj << /S /Texte /C /Texte /Pg 4 0 R /K 22 /P 430 0 R >> endobj 134 0 obj << /S /Texte /C /Texte /Pg 4 0 R /K [ 135 0 R 24 ] /P 430 0 R >> endobj 135 0 obj << /S /Underline /P 134 0 R /A 460 0 R /Pg 4 0 R /K 23 >> endobj 136 0 obj << /S /Texte /C /Texte /Pg 4 0 R /K 25 /P 430 0 R >> endobj 137 0 obj << /S /Texte /C /Texte /Pg 4 0 R /K [ 138 0 R 27 ] /P 430 0 R >> endobj 138 0 obj << /S /Underline /P 137 0 R /A 461 0 R /Pg 4 0 R /K 26 >> endobj 139 0 obj << /S /Texte /C /Texte /Pg 4 0 R /K 28 /P 430 0 R >> endobj 140 0 obj << /S /Texte /C /Texte /Pg 4 0 R /K [ 141 0 R 30 ] /P 430 0 R >> endobj 141 0 obj << /S /Underline /P 140 0 R /A 462 0 R /Pg 4 0 R /K 29 >> endobj 142 0 obj << /S /Texte /C /Texte /Pg 4 0 R /K 31 /P 430 0 R >> endobj 143 0 obj << /S /Texte /C /Texte /Pg 4 0 R /K [ 144 0 R 33 ] /P 430 0 R >> endobj 144 0 obj << /S /Underline /P 143 0 R /A 463 0 R /Pg 4 0 R /K 32 >> endobj 145 0 obj << /S /Texte /C /Texte /Pg 4 0 R /K 34 /P 430 0 R >> endobj 146 0 obj << /S /Texte /C /Texte /Pg 4 0 R /K [ 147 0 R 36 ] /P 430 0 R >> endobj 147 0 obj << /S /Underline /P 146 0 R /A 464 0 R /Pg 4 0 R /K 35 >> endobj 148 0 obj << /S /Texte /C /Texte /Pg 4 0 R /K 37 /P 430 0 R >> endobj 149 0 obj << /S /Texte /C /Texte /Pg 4 0 R /K [ 150 0 R 39 151 0 R ] /P 430 0 R >> endobj 150 0 obj << /S /Underline /P 149 0 R /A 465 0 R /Pg 4 0 R /K 38 >> endobj 151 0 obj << /S /Underline /P 149 0 R /A 466 0 R /Pg 4 0 R /K 40 >> endobj 152 0 obj << /S /Texte /C /Texte /Pg 4 0 R /K 41 /P 430 0 R >> endobj 153 0 obj << /S /Texte /C /Texte /Pg 4 0 R /K [ 154 0 R 43 ] /P 430 0 R >> endobj 154 0 obj << /S /Underline /P 153 0 R /A 467 0 R /Pg 4 0 R /K 42 >> endobj 155 0 obj << /S /Texte /C /Texte /Pg 4 0 R /K 44 /P 430 0 R >> endobj 156 0 obj << /S /Normal /A [ 157 0 R ] /C /Normal /Pg 4 0 R /K [ 158 0 R 46 ] /P 430 0 R >> endobj 157 0 obj << /O /Layout /TextAlign /Justify >> endobj 158 0 obj << /S /Underline /P 156 0 R /A 468 0 R /Pg 4 0 R /K 45 >> endobj 159 0 obj << /S /Normal /A [ 160 0 R ] /C /Normal /Pg 4 0 R /K 47 /P 430 0 R >> endobj 160 0 obj << /O /Layout /TextAlign /Justify >> endobj 161 0 obj << /S /Normal /A [ 162 0 R ] /C /Normal /Pg 4 0 R /K [ 163 0 R 49 ] /P 430 0 R >> endobj 162 0 obj << /O /Layout /TextAlign /Justify >> endobj 163 0 obj << /S /Underline /P 161 0 R /A 469 0 R /Pg 4 0 R /K 48 >> endobj 164 0 obj << /S /Normal /A [ 165 0 R ] /C /Normal /Pg 4 0 R /K 50 /P 430 0 R >> endobj 165 0 obj << /O /Layout /TextAlign /Justify >> endobj 166 0 obj << /S /Body#20Text#20Indent#202 /A [ 167 0 R ] /C /Body#20Text#20Indent#202 /Pg 4 0 R /K 51 /P 430 0 R >> endobj 167 0 obj << /O /Layout /StartIndent 0 /SpaceAfter 0 >> endobj 168 0 obj << /O /Layout /WritingMode /LrTb /StartIndent 34 /EndIndent 0 /TextAlign /Justify /SpaceBefore 0 /SpaceAfter 12 /TextIndent 0 >> endobj 169 0 obj << /S /Body#20Text#20Indent#202 /A [ 170 0 R ] /C /Body#20Text#20Indent#202 /Pg 4 0 R /K 52 /P 430 0 R >> endobj 170 0 obj << /O /Layout /StartIndent 0 /SpaceAfter 0 >> endobj 171 0 obj << /S /sous-titre#202 /C /sous-titre#202 /Pg 4 0 R /K 53 /P 430 0 R >> endobj 172 0 obj << /S /Texte /C /Texte /Pg 4 0 R /K 54 /P 430 0 R >> endobj 173 0 obj << /S /Texte /C /Texte /Pg 4 0 R /K 55 /P 430 0 R >> endobj 174 0 obj << /S /Texte /C /Texte /Pg 4 0 R /K 56 /P 430 0 R >> endobj 175 0 obj << /S /Texte /C /Texte /Pg 4 0 R /K 57 /P 430 0 R >> endobj 176 0 obj << /S /sous-titre#202 /C /sous-titre#202 /Pg 4 0 R /K 58 /P 430 0 R >> endobj 177 0 obj << /S /sous-titre#202 /C /sous-titre#202 /Pg 4 0 R /K 59 /P 430 0 R >> endobj 178 0 obj << /S /Titre#202 /A [ 179 0 R ] /C /Titre#202 /Pg 4 0 R /K 60 /P 430 0 R >> endobj 179 0 obj << /O /Layout /TextAlign /Justify /SpaceBefore 0 /SpaceAfter 0 >> endobj 180 0 obj << /O /Layout /WritingMode /LrTb /StartIndent 0 /EndIndent 0 /TextAlign /Start /SpaceBefore 12 /SpaceAfter 3 /TextIndent 0 >> endobj 181 0 obj << /S /Normal /A [ 182 0 R ] /C /Normal /Pg 4 0 R /K 61 /P 430 0 R >> endobj 182 0 obj << /O /Layout /StartIndent 36 /TextAlign /Justify /TextIndent -17.99998 >> endobj 183 0 obj << /S /Normal /A [ 184 0 R ] /C /Normal /Pg 4 0 R /K 62 /P 430 0 R >> endobj 184 0 obj << /O /Layout /StartIndent 18 /TextAlign /Justify >> endobj 185 0 obj << /S /Normal /A [ 186 0 R ] /C /Normal /Pg 4 0 R /K 63 /P 430 0 R >> endobj 186 0 obj << /O /Layout /StartIndent 36 /TextAlign /Justify /TextIndent -17.99998 >> endobj 187 0 obj << /S /Texte /C /Texte /Pg 4 0 R /K 64 /P 430 0 R >> endobj 188 0 obj << /S /Texte /C /Texte /Pg 4 0 R /K 65 /P 430 0 R >> endobj 189 0 obj << /S /Texte /C /Texte /Pg 7 0 R /K 0 /P 430 0 R >> endobj 190 0 obj << /S /Texte /C /Texte /Pg 7 0 R /K 1 /P 430 0 R >> endobj 191 0 obj << /S /sous-titre#202 /C /sous-titre#202 /Pg 7 0 R /K 2 /P 430 0 R >> endobj 192 0 obj << /S /Texte /C /Texte /Pg 7 0 R /K 3 /P 430 0 R >> endobj 193 0 obj << /S /Texte /C /Texte /Pg 7 0 R /K 4 /P 430 0 R >> endobj 194 0 obj << /S /Texte /C /Texte /Pg 7 0 R /K 5 /P 430 0 R >> endobj 195 0 obj << /S /Texte /C /Texte /Pg 7 0 R /K 6 /P 430 0 R >> endobj 196 0 obj << /S /Texte /C /Texte /Pg 7 0 R /K 7 /P 430 0 R >> endobj 197 0 obj << /S /Texte /C /Texte /Pg 7 0 R /K 8 /P 430 0 R >> endobj 198 0 obj << /S /Texte /C /Texte /Pg 7 0 R /K 9 /P 430 0 R >> endobj 199 0 obj << /S /Texte /C /Texte /Pg 7 0 R /K 10 /P 430 0 R >> endobj 200 0 obj << /S /Texte /C /Texte /Pg 7 0 R /K 11 /P 430 0 R >> endobj 201 0 obj << /S /Texte /C /Texte /Pg 7 0 R /K 12 /P 430 0 R >> endobj 202 0 obj << /S /sous-titre#202 /A [ 203 0 R ] /C /sous-titre#202 /Pg 7 0 R /K 13 /P 430 0 R >> endobj 203 0 obj << /O /Layout /EndIndent -14.24998 >> endobj 204 0 obj << /S /Texte#20Car /C /Texte#20Car /Pg 7 0 R /K 14 /P 430 0 R >> endobj 205 0 obj << /S /Texte /C /Texte /Pg 7 0 R /K 15 /P 430 0 R >> endobj 206 0 obj << /S /Texte /C /Texte /Pg 7 0 R /K 16 /P 430 0 R >> endobj 207 0 obj << /S /Texte /C /Texte /Pg 7 0 R /K 17 /P 430 0 R >> endobj 208 0 obj << /S /Texte /C /Texte /Pg 7 0 R /K 18 /P 430 0 R >> endobj 209 0 obj << /S /Texte /C /Texte /Pg 7 0 R /K 19 /P 430 0 R >> endobj 210 0 obj << /S /Body#20Text#20Indent#202 /A [ 211 0 R ] /C /Body#20Text#20Indent#202 /Pg 7 0 R /K 20 /P 430 0 R >> endobj 211 0 obj << /O /Layout /StartIndent 0 /SpaceAfter 0 >> endobj 212 0 obj << /S /Body#20Text#20Indent#202 /A [ 213 0 R ] /C /Body#20Text#20Indent#202 /Pg 7 0 R /K 21 /P 430 0 R >> endobj 213 0 obj << /O /Layout /StartIndent 0 /SpaceAfter 0 >> endobj 214 0 obj << /S /Body#20Text#20Indent#202 /A [ 215 0 R ] /C /Body#20Text#20Indent#202 /Pg 7 0 R /K 22 /P 430 0 R >> endobj 215 0 obj << /O /Layout /StartIndent 0 /SpaceAfter 0 >> endobj 216 0 obj << /S /LBody /A [ 217 0 R ] /C /Body#20Text#20Indent#202 /Pg 7 0 R /K 23 /P 432 0 R >> endobj 217 0 obj << /O /Layout /StartIndent 32.2 /SpaceAfter 0 /TextIndent -17.99998 >> endobj 218 0 obj << /S /Body#20Text#20Indent#202 /A [ 219 0 R ] /C /Body#20Text#20Indent#202 /Pg 7 0 R /K 24 /P 430 0 R >> endobj 219 0 obj << /O /Layout /StartIndent 14.2 /TextAlign /Start /SpaceAfter 0 >> endobj 220 0 obj << /S /LBody /A [ 221 0 R ] /C /Body#20Text#20Indent#202 /Pg 7 0 R /K 25 /P 433 0 R >> endobj 221 0 obj << /O /Layout /StartIndent 32.2 /TextAlign /Start /SpaceAfter 0 /TextIndent -17.99998 >> endobj 222 0 obj << /S /Body#20Text#20Indent#202 /A [ 223 0 R ] /C /Body#20Text#20Indent#202 /Pg 7 0 R /K 26 /P 430 0 R >> endobj 223 0 obj << /O /Layout /StartIndent 14.2 /TextAlign /Start /SpaceAfter 0 >> endobj 224 0 obj << /S /LBody /A [ 225 0 R ] /C /Body#20Text#20Indent#202 /Pg 7 0 R /K 27 /P 434 0 R >> endobj 225 0 obj << /O /Layout /StartIndent 0 /SpaceAfter 0 /TextIndent 14.2 >> endobj 226 0 obj << /S /Texte#20Car /C /Texte#20Car /Pg 7 0 R /K 28 /P 430 0 R >> endobj 227 0 obj << /S /sous-titre#202 /C /sous-titre#202 /Pg 7 0 R /K 29 /P 430 0 R >> endobj 228 0 obj << /S /sous-titre#202 /C /sous-titre#202 /Pg 7 0 R /K 30 /P 430 0 R >> endobj 229 0 obj << /S /Body#20Text#20Indent#202 /A [ 230 0 R ] /C /Body#20Text#20Indent#202 /Pg 7 0 R /K 31 /P 430 0 R >> endobj 230 0 obj << /O /Layout /StartIndent 0 >> endobj 231 0 obj << /S /Texte#20Car /C /Texte#20Car /Pg 7 0 R /K 32 /P 430 0 R >> endobj 232 0 obj << /S /sous-titre#202 /C /sous-titre#202 /Pg 7 0 R /K 33 /P 430 0 R >> endobj 233 0 obj << /S /sous-titre#202 /C /sous-titre#202 /Pg 7 0 R /K 34 /P 430 0 R >> endobj 234 0 obj << /S /sous-titre#202 /C /sous-titre#202 /Pg 7 0 R /K 35 /P 430 0 R >> endobj 235 0 obj << /S /Texte /C /Texte /Pg 7 0 R /K 36 /P 430 0 R >> endobj 236 0 obj << /S /Texte /C /Texte /Pg 7 0 R /K 37 /P 430 0 R >> endobj 237 0 obj << /S /Normal /A [ 238 0 R ] /C /Normal /Pg 7 0 R /K 38 /P 430 0 R >> endobj 238 0 obj << /O /Layout /StartIndent 35.45 >> endobj 239 0 obj << /S /Normal /C /Normal /Pg 7 0 R /K 39 /P 430 0 R >> endobj 240 0 obj << /S /Body#20Text#202 /C /Body#20Text#202 /Pg 7 0 R /K 40 /P 430 0 R >> endobj 241 0 obj << /S /Body#20Text#202 /A [ 242 0 R ] /C /Body#20Text#202 /Pg 7 0 R /K 41 /P 430 0 R >> endobj 242 0 obj << /O /Layout /SpaceAfter 6 >> endobj 243 0 obj << /S /LBody /A [ 244 0 R ] /C /Body#20Text#202 /Pg 7 0 R /K 42 /P 436 0 R >> endobj 244 0 obj << /O /Layout /StartIndent 32.2 /TextAlign /Start /SpaceAfter 6 /TextIndent -17.99998 >> endobj 245 0 obj << /S /LBody /A [ 246 0 R ] /C /Texte /Pg 7 0 R /K 43 /P 437 0 R >> endobj 246 0 obj << /O /Layout /StartIndent 32.2 /TextIndent -17.99998 >> endobj 247 0 obj << /S /Texte /C /Texte /Pg 7 0 R /K 44 /P 430 0 R >> endobj 248 0 obj << /S /Normal /A [ 249 0 R ] /C /Normal /Pg 7 0 R /K 45 /P 430 0 R >> endobj 249 0 obj << /O /Layout /TextAlign /Justify >> endobj 250 0 obj << /S /Texte /C /Texte /Pg 7 0 R /K 46 /P 430 0 R >> endobj 251 0 obj << /S /Texte /C /Texte /Pg 7 0 R /K 47 /P 430 0 R >> endobj 252 0 obj << /S /Texte /C /Texte /Pg 7 0 R /K 48 /P 430 0 R >> endobj 253 0 obj << /S /Normal /A [ 254 0 R ] /C /Normal /Pg 7 0 R /K 49 /P 430 0 R >> endobj 254 0 obj << /O /Layout /TextAlign /Justify >> endobj 255 0 obj << /S /Normal /A [ 256 0 R ] /C /Normal /Pg 10 0 R /K 0 /P 430 0 R >> endobj 256 0 obj << /O /Layout /TextAlign /Justify >> endobj 257 0 obj << /S /Corps#20de#20texte#202 /C /Corps#20de#20texte#202 /Pg 10 0 R /K 1 /P 430 0 R >> endobj 258 0 obj << /S /Normal /A [ 260 0 R ] /C /Normal /Pg 10 0 R /K 2 /P 430 0 R >> endobj 259 0 obj << /O /Layout /WritingMode /LrTb /StartIndent 0 /EndIndent 0 /TextAlign /Justify /SpaceBefore 0 /SpaceAfter 0 /TextIndent 0 >> endobj 260 0 obj << /O /Layout /TextAlign /Justify >> endobj 261 0 obj << /S /LBody /A [ 262 0 R ] /C /Body#20Text#202 /Pg 10 0 R /K 3 /P 439 0 R >> endobj 262 0 obj << /O /Layout /StartIndent 32.2 /TextAlign /Start /SpaceAfter 6 /TextIndent -17.99998 >> endobj 263 0 obj << /S /LBody /A [ 264 0 R ] /C /Texte /Pg 10 0 R /K 4 /P 440 0 R >> endobj 264 0 obj << /O /Layout /StartIndent 32.2 /TextIndent -17.99998 >> endobj 265 0 obj << /S /Normal /C /Normal /Pg 10 0 R /K 5 /P 430 0 R >> endobj 266 0 obj << /S /Normal /A [ 267 0 R ] /C /Normal /Pg 10 0 R /K 6 /P 430 0 R >> endobj 267 0 obj << /O /Layout /TextAlign /Justify >> endobj 268 0 obj << /S /Normal /A [ 269 0 R ] /C /Normal /Pg 10 0 R /K 7 /P 430 0 R >> endobj 269 0 obj << /O /Layout /TextAlign /Justify >> endobj 270 0 obj << /S /Texte /C /Texte /Pg 10 0 R /K 8 /P 430 0 R >> endobj 271 0 obj << /S /Texte /C /Texte /Pg 10 0 R /K 9 /P 430 0 R >> endobj 272 0 obj << /S /Texte /C /Texte /Pg 10 0 R /K 10 /P 430 0 R >> endobj 273 0 obj << /S /Texte /C /Texte /Pg 10 0 R /K 11 /P 430 0 R >> endobj 274 0 obj << /S /Texte /C /Texte /Pg 10 0 R /K 12 /P 430 0 R >> endobj 275 0 obj << /S /Texte /C /Texte /Pg 10 0 R /K 13 /P 430 0 R >> endobj 276 0 obj << /S /Normal /A [ 277 0 R ] /C /Normal /Pg 10 0 R /K 14 /P 430 0 R >> endobj 277 0 obj << /O /Layout /TextAlign /Justify >> endobj 278 0 obj << /S /Normal /A [ 279 0 R ] /C /Normal /Pg 10 0 R /K 15 /P 430 0 R >> endobj 279 0 obj << /O /Layout /TextAlign /Justify >> endobj 280 0 obj << /S /Texte /C /Texte /Pg 10 0 R /K 16 /P 430 0 R >> endobj 281 0 obj << /S /sous-titre#202 /A [ 282 0 R ] /C /sous-titre#202 /Pg 10 0 R /K 17 /P 430 0 R >> endobj 282 0 obj << /O /Layout /EndIndent -14.24998 >> endobj 283 0 obj << /S /sous-titre#202 /A [ 284 0 R ] /C /sous-titre#202 /Pg 10 0 R /K 18 /P 430 0 R >> endobj 284 0 obj << /O /Layout /EndIndent -14.24998 >> endobj 285 0 obj << /S /sous-titre#202 /A [ 286 0 R ] /C /sous-titre#202 /Pg 10 0 R /K 19 /P 430 0 R >> endobj 286 0 obj << /O /Layout /EndIndent -14.24998 >> endobj 287 0 obj << /S /sous-titre#202 /A [ 288 0 R ] /C /sous-titre#202 /Pg 10 0 R /K 20 /P 430 0 R >> endobj 288 0 obj << /O /Layout /EndIndent -14.24998 >> endobj 289 0 obj << /S /sous-titre#202 /A [ 290 0 R ] /C /sous-titre#202 /Pg 10 0 R /K 21 /P 430 0 R >> endobj 290 0 obj << /O /Layout /EndIndent -14.24998 >> endobj 291 0 obj << /S /sous-titre#202 /A [ 292 0 R ] /C /sous-titre#202 /Pg 10 0 R /K 22 /P 430 0 R >> endobj 292 0 obj << /O /Layout /EndIndent -14.24998 >> endobj 293 0 obj << /S /sous-titre#202 /A [ 294 0 R ] /C /sous-titre#202 /Pg 10 0 R /K 23 /P 430 0 R >> endobj 294 0 obj << /O /Layout /EndIndent -14.24998 >> endobj 295 0 obj << /S /sous-titre#202 /C /sous-titre#202 /Pg 10 0 R /K 24 /P 430 0 R >> endobj 296 0 obj << /S /Texte /C /Texte /Pg 10 0 R /K 25 /P 430 0 R >> endobj 297 0 obj << /S /Texte /C /Texte /Pg 10 0 R /K 26 /P 430 0 R >> endobj 298 0 obj << /S /Texte /C /Texte /Pg 10 0 R /K 27 /P 430 0 R >> endobj 299 0 obj << /S /Texte /C /Texte /Pg 10 0 R /K 28 /P 430 0 R >> endobj 300 0 obj << /S /Texte /C /Texte /Pg 10 0 R /K 29 /P 430 0 R >> endobj 301 0 obj << /S /Texte /C /Texte /Pg 10 0 R /K 30 /P 430 0 R >> endobj 302 0 obj << /S /Texte /C /Texte /Pg 10 0 R /K 31 /P 430 0 R >> endobj 303 0 obj << /S /Texte /C /Texte /Pg 10 0 R /K 32 /P 430 0 R >> endobj 304 0 obj << /S /Texte /C /Texte /Pg 10 0 R /K 33 /P 430 0 R >> endobj 305 0 obj << /S /Texte /C /Texte /Pg 10 0 R /K 34 /P 430 0 R >> endobj 306 0 obj << /S /Texte /C /Texte /Pg 10 0 R /K 35 /P 430 0 R >> endobj 307 0 obj << /S /Texte /C /Texte /Pg 10 0 R /K 36 /P 430 0 R >> endobj 308 0 obj << /S /Texte /C /Texte /Pg 10 0 R /K 37 /P 430 0 R >> endobj 309 0 obj << /S /Texte /C /Texte /Pg 10 0 R /K 38 /P 430 0 R >> endobj 310 0 obj << /S /Texte /C /Texte /Pg 10 0 R /K 39 /P 430 0 R >> endobj 311 0 obj << /S /Texte /A [ 312 0 R ] /C /Texte /Pg 10 0 R /K 40 /P 430 0 R >> endobj 312 0 obj << /O /Layout /EndIndent -14.24998 /TextAlign /Start >> endobj 313 0 obj << /S /Texte /A [ 314 0 R ] /C /Texte /Pg 10 0 R /K 41 /P 430 0 R >> endobj 314 0 obj << /O /Layout /EndIndent -14.24998 /TextAlign /Start >> endobj 315 0 obj << /S /LBody /A [ 316 0 R ] /C /Normal /Pg 10 0 R /K 42 /P 442 0 R >> endobj 316 0 obj << /O /Layout /StartIndent 32.2 /TextAlign /Justify /TextIndent -17.99998 >> endobj 317 0 obj << /S /Normal /A [ 318 0 R ] /C /Normal /Pg 10 0 R /K 43 /P 430 0 R >> endobj 318 0 obj << /O /Layout /StartIndent 14.2 /TextAlign /Justify >> endobj 319 0 obj << /S /LBody /A [ 320 0 R ] /C /En-t#C3#AAte /Pg 10 0 R /K 44 /P 443 0 R >> endobj 320 0 obj << /O /Layout /StartIndent 32.2 /TextAlign /Justify /TextIndent -17.99998 >> endobj 321 0 obj << /O /Layout /WritingMode /LrTb /StartIndent 0 /EndIndent 0 /TextAlign /Start /SpaceBefore 0 /SpaceAfter 0 /TextIndent 0 >> endobj 322 0 obj << /S /Texte /A [ 323 0 R ] /C /Texte /Pg 10 0 R /K 45 /P 430 0 R >> endobj 323 0 obj << /O /Layout /EndIndent -14.24998 /TextAlign /Start >> endobj 324 0 obj << /S /Texte /C /Texte /Pg 10 0 R /K 46 /P 430 0 R >> endobj 325 0 obj << /S /sous-titre#202 /C /sous-titre#202 /Pg 10 0 R /K 47 /P 430 0 R >> endobj 326 0 obj << /S /sous-titre#202 /C /sous-titre#202 /Pg 10 0 R /K 48 /P 430 0 R >> endobj 327 0 obj << /S /sous-titre#202 /C /sous-titre#202 /Pg 10 0 R /K 49 /P 430 0 R >> endobj 328 0 obj << /S /sous-titre#202 /C /sous-titre#202 /Pg 10 0 R /K 50 /P 430 0 R >> endobj 329 0 obj << /S /sous-titre#202 /C /sous-titre#202 /Pg 10 0 R /K 51 /P 430 0 R >> endobj 330 0 obj << /S /sous-titre#202 /C /sous-titre#202 /Pg 10 0 R /K 52 /P 430 0 R >> endobj 331 0 obj << /S /sous-titre#202 /C /sous-titre#202 /Pg 10 0 R /K 53 /P 430 0 R >> endobj 332 0 obj << /S /Titre#202 /A [ 333 0 R ] /C /Titre#202 /Pg 10 0 R /K 54 /P 430 0 R >> endobj 333 0 obj << /O /Layout /TextAlign /Justify >> endobj 334 0 obj << /S /Normal /C /Normal /Pg 10 0 R /K 55 /P 430 0 R >> endobj 335 0 obj << /S /Texte /C /Texte /Pg 10 0 R /P 430 0 R /K [ 56 << /Type /MCR /Pg 13 0 R /MCID 0 >> ] >> endobj 336 0 obj << /S /Texte /C /Texte /Pg 13 0 R /K 1 /P 430 0 R >> endobj 337 0 obj << /S /Texte /C /Texte /Pg 13 0 R /K 2 /P 430 0 R >> endobj 338 0 obj << /S /Texte /C /Texte /Pg 13 0 R /K 3 /P 430 0 R >> endobj 339 0 obj << /S /Texte /C /Texte /Pg 13 0 R /K 4 /P 430 0 R >> endobj 340 0 obj << /S /sous-titre#202 /C /sous-titre#202 /Pg 13 0 R /K 5 /P 430 0 R >> endobj 341 0 obj << /S /Texte /C /Texte /Pg 13 0 R /K 6 /P 430 0 R >> endobj 342 0 obj << /S /Texte /C /Texte /Pg 13 0 R /K 7 /P 430 0 R >> endobj 343 0 obj << /S /Texte /C /Texte /Pg 13 0 R /K 8 /P 430 0 R >> endobj 344 0 obj << /S /Titre#202 /A [ 345 0 R ] /C /Titre#202 /Pg 13 0 R /K 9 /P 430 0 R >> endobj 345 0 obj << /O /Layout /TextAlign /Justify /SpaceBefore 0 /SpaceAfter 0 >> endobj 346 0 obj << /S /sous-titre#202 /C /sous-titre#202 /Pg 13 0 R /K 10 /P 430 0 R >> endobj 347 0 obj << /S /sous-titre#202 /C /sous-titre#202 /Pg 13 0 R /K 11 /P 430 0 R >> endobj 348 0 obj << /S /sous-titre#202 /C /sous-titre#202 /Pg 13 0 R /K 12 /P 430 0 R >> endobj 349 0 obj << /S /Texte /C /Texte /Pg 13 0 R /K 13 /P 430 0 R >> endobj 350 0 obj << /S /Titre#202 /A [ 351 0 R ] /C /Titre#202 /Pg 13 0 R /K 14 /P 430 0 R >> endobj 351 0 obj << /O /Layout /TextAlign /Justify /SpaceBefore 0 /SpaceAfter 0 >> endobj 352 0 obj << /S /Normal /A [ 353 0 R ] /C /Normal /Pg 13 0 R /K 15 /P 430 0 R >> endobj 353 0 obj << /O /Layout /TextAlign /Justify >> endobj 354 0 obj << /S /Normal /A [ 355 0 R ] /C /Normal /Pg 13 0 R /K 16 /P 430 0 R >> endobj 355 0 obj << /O /Layout /TextAlign /Justify >> endobj 356 0 obj << /S /Texte /C /Texte /Pg 13 0 R /K 17 /P 430 0 R >> endobj 357 0 obj << /S /Texte /C /Texte /Pg 13 0 R /K 18 /P 430 0 R >> endobj 358 0 obj << /S /Titre#202 /A [ 359 0 R ] /C /Titre#202 /Pg 13 0 R /K 19 /P 430 0 R >> endobj 359 0 obj << /O /Layout /TextAlign /Justify >> endobj 360 0 obj << /S /Texte /C /Texte /Pg 13 0 R /K 20 /P 430 0 R >> endobj 361 0 obj << /S /Texte /C /Texte /Pg 13 0 R /K 21 /P 430 0 R >> endobj 362 0 obj << /S /Texte /C /Texte /Pg 13 0 R /K 22 /P 430 0 R >> endobj 363 0 obj << /S /Texte /C /Texte /Pg 13 0 R /K 23 /P 430 0 R >> endobj 364 0 obj << /S /Texte /C /Texte /Pg 13 0 R /K 24 /P 430 0 R >> endobj 365 0 obj << /S /sous-titre#202 /C /sous-titre#202 /Pg 13 0 R /K 25 /P 430 0 R >> endobj 366 0 obj << /S /Texte /C /Texte /Pg 13 0 R /K 26 /P 430 0 R >> endobj 367 0 obj << /S /Titre#201 /A [ 368 0 R ] /C /Titre#201 /Pg 13 0 R /P 430 0 R /K [ 27 << /Type /MCR /Pg 16 0 R /MCID 0 >> ] >> endobj 368 0 obj << /O /Layout /TextAlign /Justify >> endobj 369 0 obj << /O /Layout /WritingMode /LrTb /StartIndent 0 /EndIndent 0 /TextAlign /Start /SpaceBefore 0 /SpaceAfter 0 /TextIndent 0 >> endobj 370 0 obj << /S /Normal /C /Normal /Pg 16 0 R /K 1 /P 430 0 R >> endobj 371 0 obj << /S /Normal /A [ 372 0 R ] /C /Normal /Pg 16 0 R /K 2 /P 430 0 R >> endobj 372 0 obj << /O /Layout /TextAlign /Justify >> endobj 373 0 obj << /S /Normal /A [ 374 0 R ] /C /Normal /Pg 16 0 R /K 3 /P 430 0 R >> endobj 374 0 obj << /O /Layout /TextAlign /Justify >> endobj 375 0 obj << /S /sous-titre#202 /C /sous-titre#202 /Pg 16 0 R /K 4 /P 430 0 R >> endobj 376 0 obj << /S /sous-titre#202 /C /sous-titre#202 /Pg 16 0 R /K 5 /P 430 0 R >> endobj 377 0 obj << /S /sous-titre#202 /C /sous-titre#202 /Pg 16 0 R /K 6 /P 430 0 R >> endobj 378 0 obj << /S /Normal /A [ 379 0 R ] /C /Normal /Pg 16 0 R /K 7 /P 430 0 R >> endobj 379 0 obj << /O /Layout /TextAlign /Justify >> endobj 380 0 obj << /S /Normal /A [ 381 0 R ] /C /Normal /Pg 16 0 R /K 8 /P 430 0 R >> endobj 381 0 obj << /O /Layout /TextAlign /Justify >> endobj 382 0 obj << /S /Normal /A [ 383 0 R ] /C /Normal /Pg 16 0 R /K 9 /P 430 0 R >> endobj 383 0 obj << /O /Layout /TextAlign /Justify >> endobj 384 0 obj << /S /Normal /A [ 385 0 R ] /C /Normal /Pg 16 0 R /K 10 /P 430 0 R >> endobj 385 0 obj << /O /Layout /TextAlign /Justify >> endobj 386 0 obj << /S /Normal /A [ 387 0 R ] /C /Normal /Pg 16 0 R /K 11 /P 430 0 R >> endobj 387 0 obj << /O /Layout /TextAlign /Justify >> endobj 388 0 obj << /S /Normal /A [ 389 0 R ] /C /Normal /Pg 16 0 R /K 12 /P 430 0 R >> endobj 389 0 obj << /O /Layout /TextAlign /Justify >> endobj 390 0 obj << /S /Normal /A [ 391 0 R ] /C /Normal /Pg 16 0 R /K 13 /P 430 0 R >> endobj 391 0 obj << /O /Layout /TextAlign /Justify >> endobj 392 0 obj << /S /Normal /A [ 393 0 R ] /C /Normal /Pg 16 0 R /K 14 /P 430 0 R >> endobj 393 0 obj << /O /Layout /TextAlign /Justify >> endobj 394 0 obj << /S /Normal /A [ 395 0 R ] /C /Normal /Pg 16 0 R /K 15 /P 430 0 R >> endobj 395 0 obj << /O /Layout /TextAlign /Justify >> endobj 396 0 obj << /S /Normal /C /Normal /Pg 16 0 R /K 16 /P 430 0 R >> endobj 397 0 obj << /S /Normal /A [ 398 0 R ] /C /Normal /Pg 16 0 R /K 17 /P 430 0 R >> endobj 398 0 obj << /O /Layout /TextAlign /Justify >> endobj 399 0 obj << /S /Normal /A [ 400 0 R ] /C /Normal /Pg 16 0 R /K 18 /P 430 0 R >> endobj 400 0 obj << /O /Layout /TextAlign /Justify >> endobj 401 0 obj << /S /Normal /A [ 402 0 R ] /C /Normal /Pg 16 0 R /K 19 /P 430 0 R >> endobj 402 0 obj << /O /Layout /TextAlign /Justify >> endobj 403 0 obj << /S /sous-titre#202 /A [ 404 0 R ] /C /sous-titre#202 /Pg 16 0 R /K 20 /P 430 0 R >> endobj 404 0 obj << /O /Layout /TextAlign /Justify >> endobj 405 0 obj << /S /sous-titre#202 /C /sous-titre#202 /Pg 16 0 R /K 21 /P 430 0 R >> endobj 406 0 obj << /S /Normal /A [ 407 0 R ] /C /Normal /Pg 16 0 R /K 22 /P 430 0 R >> endobj 407 0 obj << /O /Layout /TextAlign /Justify >> endobj 408 0 obj << /S /Normal /A [ 409 0 R ] /C /Normal /Pg 16 0 R /K 23 /P 430 0 R >> endobj 409 0 obj << /O /Layout /TextAlign /Justify >> endobj 410 0 obj << /S /Normal /A [ 411 0 R ] /C /Normal /Pg 16 0 R /K 24 /P 430 0 R >> endobj 411 0 obj << /O /Layout /TextAlign /Justify >> endobj 412 0 obj << /S /Normal /A [ 413 0 R ] /C /Normal /Pg 16 0 R /K 25 /P 430 0 R >> endobj 413 0 obj << /O /Layout /TextAlign /Justify >> endobj 414 0 obj << /S /Normal /A [ 415 0 R ] /C /Normal /Pg 16 0 R /K 26 /P 430 0 R >> endobj 415 0 obj << /O /Layout /TextAlign /Justify >> endobj 416 0 obj << /S /Normal /C /Normal /Pg 16 0 R /K 27 /P 430 0 R >> endobj 417 0 obj << /S /Normal /C /Normal /Pg 16 0 R /K 28 /P 430 0 R >> endobj 418 0 obj << /S /sous-titre#202 /C /sous-titre#202 /Pg 16 0 R /K 29 /P 430 0 R >> endobj 419 0 obj << /S /sous-titre#202 /C /sous-titre#202 /Pg 16 0 R /K 30 /P 430 0 R >> endobj 420 0 obj << /S /sous-titre#202 /A [ 421 0 R ] /C /sous-titre#202 /Pg 16 0 R /K 31 /P 430 0 R >> endobj 421 0 obj << /O /Layout /TextAlign /Justify >> endobj 422 0 obj << /S /sous-titre#202 /A [ 423 0 R ] /C /sous-titre#202 /Pg 16 0 R /K 32 /P 430 0 R >> endobj 423 0 obj << /O /Layout /TextAlign /Justify >> endobj 424 0 obj << /S /sous-titre#202 /A [ 425 0 R ] /C /sous-titre#202 /Pg 16 0 R /K 33 /P 430 0 R >> endobj 425 0 obj << /O /Layout /TextAlign /Justify >> endobj 426 0 obj << /S /Note#20de#20bas#20de#20page /C /Note#20de#20bas#20de#20page /Pg 482 0 R /K 26 /P 444 0 R >> endobj 427 0 obj << /O /Layout /WritingMode /LrTb /StartIndent 0 /EndIndent 0 /TextAlign /Start /SpaceBefore 0 /SpaceAfter 0 /TextIndent 0 >> endobj 428 0 obj << /O /Layout /WritingMode /LrTb /StartIndent 56.7 /EndIndent 0 /TextAlign /Start /SpaceBefore 0 /SpaceAfter 0 /TextIndent 0 >> endobj 429 0 obj << /S /Sect /P 481 0 R /K [ 43 0 R 47 0 R 48 0 R 49 0 R 445 0 R 51 0 R 53 0 R 54 0 R 55 0 R 56 0 R 446 0 R 57 0 R 61 0 R 63 0 R 64 0 R 67 0 R 70 0 R 72 0 R 74 0 R 76 0 R 78 0 R 80 0 R 82 0 R 84 0 R 86 0 R 88 0 R 444 0 R 89 0 R 91 0 R 92 0 R 94 0 R 97 0 R 99 0 R 101 0 R 103 0 R 104 0 R 105 0 R 107 0 R 108 0 R 109 0 R ] >> endobj 430 0 obj << /S /Sect /P 481 0 R /K [ 110 0 R 112 0 R 113 0 R 115 0 R 116 0 R 118 0 R 119 0 R 121 0 R 122 0 R 124 0 R 125 0 R 127 0 R 128 0 R 130 0 R 131 0 R 133 0 R 134 0 R 136 0 R 137 0 R 139 0 R 140 0 R 142 0 R 143 0 R 145 0 R 146 0 R 148 0 R 149 0 R 152 0 R 153 0 R 155 0 R 156 0 R 159 0 R 161 0 R 164 0 R 166 0 R 169 0 R 171 0 R 172 0 R 173 0 R 174 0 R 175 0 R 176 0 R 177 0 R 178 0 R 181 0 R 183 0 R 185 0 R 187 0 R 188 0 R 189 0 R 190 0 R 191 0 R 192 0 R 193 0 R 194 0 R 195 0 R 196 0 R 197 0 R 198 0 R 199 0 R 200 0 R 201 0 R 202 0 R 204 0 R 205 0 R 206 0 R 207 0 R 208 0 R 209 0 R 210 0 R 212 0 R 214 0 R 431 0 R 218 0 R 222 0 R 226 0 R 227 0 R 228 0 R 229 0 R 231 0 R 232 0 R 233 0 R 234 0 R 235 0 R 236 0 R 237 0 R 239 0 R 240 0 R 241 0 R 435 0 R 247 0 R 248 0 R 250 0 R 251 0 R 252 0 R 253 0 R 255 0 R 257 0 R 258 0 R 438 0 R 265 0 R 266 0 R 268 0 R 270 0 R 271 0 R 272 0 R 273 0 R 274 0 R 275 0 R 276 0 R 278 0 R 280 0 R 281 0 R 283 0 R 285 0 R 287 0 R 289 0 R 291 0 R 293 0 R 295 0 R 296 0 R 297 0 R 298 0 R 299 0 R 300 0 R 301 0 R 302 0 R 303 0 R 304 0 R 305 0 R 306 0 R 307 0 R 308 0 R 309 0 R 310 0 R 311 0 R 313 0 R 441 0 R 317 0 R 322 0 R 324 0 R 325 0 R 326 0 R 327 0 R 328 0 R 329 0 R 330 0 R 331 0 R 332 0 R 334 0 R 335 0 R 336 0 R 337 0 R 338 0 R 339 0 R 340 0 R 341 0 R 342 0 R 343 0 R 344 0 R 346 0 R 347 0 R 348 0 R 349 0 R 350 0 R 352 0 R 354 0 R 356 0 R 357 0 R 358 0 R 360 0 R 361 0 R 362 0 R 363 0 R 364 0 R 365 0 R 366 0 R 367 0 R 370 0 R 371 0 R 373 0 R 375 0 R 376 0 R 377 0 R 378 0 R 380 0 R 382 0 R 384 0 R 386 0 R 388 0 R 390 0 R 392 0 R 394 0 R 396 0 R 397 0 R 399 0 R 401 0 R 403 0 R 405 0 R 406 0 R 408 0 R 410 0 R 412 0 R 414 0 R 416 0 R 417 0 R 418 0 R 419 0 R 420 0 R 422 0 R 424 0 R ] >> endobj 431 0 obj << /S /L /P 430 0 R /K [ 432 0 R 433 0 R 434 0 R ] >> endobj 432 0 obj << /S /LI /P 431 0 R /K 216 0 R >> endobj 433 0 obj << /S /LI /P 431 0 R /K 220 0 R >> endobj 434 0 obj << /S /LI /P 431 0 R /K 224 0 R >> endobj 435 0 obj << /S /L /P 430 0 R /K [ 436 0 R 437 0 R ] >> endobj 436 0 obj << /S /LI /P 435 0 R /K 243 0 R >> endobj 437 0 obj << /S /LI /P 435 0 R /K 245 0 R >> endobj 438 0 obj << /S /L /P 430 0 R /K [ 439 0 R 440 0 R ] >> endobj 439 0 obj << /S /LI /P 438 0 R /K 261 0 R >> endobj 440 0 obj << /S /LI /P 438 0 R /K 263 0 R >> endobj 441 0 obj << /S /L /P 430 0 R /K [ 442 0 R 443 0 R ] >> endobj 442 0 obj << /S /LI /P 441 0 R /K 315 0 R >> endobj 443 0 obj << /S /LI /P 441 0 R /K 319 0 R >> endobj 444 0 obj << /S /Footnote /P 429 0 R /K 426 0 R >> endobj 445 0 obj << /S /Shape /Alt () /Pg 482 0 R /K 27 /P 429 0 R /A 450 0 R >> endobj 446 0 obj << /S /Shape /Alt () /Pg 482 0 R /K [ 28 29 ] /P 429 0 R /A 451 0 R >> endobj 447 0 obj << /Nums [ 0 448 0 R 1 452 0 R 2 453 0 R 3 470 0 R 4 471 0 R 5 472 0 R 6 473 0 R ] >> endobj 448 0 obj [ 43 0 R 47 0 R 48 0 R 49 0 R 51 0 R 53 0 R 54 0 R 55 0 R 56 0 R 57 0 R 61 0 R 63 0 R 64 0 R 67 0 R 69 0 R 67 0 R 70 0 R 72 0 R 74 0 R 76 0 R 78 0 R 80 0 R 82 0 R 84 0 R 86 0 R 88 0 R 426 0 R 445 0 R 446 0 R 446 0 R ] endobj 449 0 obj << /O /Layout /BaselineShift 5 >> endobj 450 0 obj << /O /Layout /BBox [ 110 626 655 628 ] /Placement /Block /StartIndent -3.40001 /EndIndent -102.54999 >> endobj 451 0 obj << /O /Layout /BBox [ -5.99998 546 617 561 ] /Placement /Block /StartIndent -119.39999 /EndIndent -64.54999 >> endobj 452 0 obj [ 89 0 R 91 0 R 92 0 R 94 0 R 97 0 R 99 0 R 101 0 R 103 0 R 104 0 R 105 0 R 107 0 R 108 0 R ] endobj 453 0 obj [ 109 0 R 110 0 R 112 0 R 113 0 R 115 0 R 117 0 R 116 0 R 118 0 R 120 0 R 119 0 R 121 0 R 123 0 R 122 0 R 124 0 R 126 0 R 125 0 R 127 0 R 129 0 R 128 0 R 130 0 R 132 0 R 131 0 R 133 0 R 135 0 R 134 0 R 136 0 R 138 0 R 137 0 R 139 0 R 141 0 R 140 0 R 142 0 R 144 0 R 143 0 R 145 0 R 147 0 R 146 0 R 148 0 R 150 0 R 149 0 R 151 0 R 152 0 R 154 0 R 153 0 R 155 0 R 158 0 R 156 0 R 159 0 R 163 0 R 161 0 R 164 0 R 166 0 R 169 0 R 171 0 R 172 0 R 173 0 R 174 0 R 175 0 R 176 0 R 177 0 R 178 0 R 181 0 R 183 0 R 185 0 R 187 0 R 188 0 R ] endobj 454 0 obj << /O /Layout /TextDecorationType /Underline >> endobj 455 0 obj << /O /Layout /TextDecorationType /Underline >> endobj 456 0 obj << /O /Layout /TextDecorationType /Underline >> endobj 457 0 obj << /O /Layout /TextDecorationType /Underline >> endobj 458 0 obj << /O /Layout /TextDecorationType /Underline >> endobj 459 0 obj << /O /Layout /TextDecorationType /Underline >> endobj 460 0 obj << /O /Layout /TextDecorationType /Underline >> endobj 461 0 obj << /O /Layout /TextDecorationType /Underline >> endobj 462 0 obj << /O /Layout /TextDecorationType /Underline >> endobj 463 0 obj << /O /Layout /TextDecorationType /Underline >> endobj 464 0 obj << /O /Layout /TextDecorationType /Underline >> endobj 465 0 obj << /O /Layout /TextDecorationType /Underline >> endobj 466 0 obj << /O /Layout /TextDecorationType /Underline >> endobj 467 0 obj << /O /Layout /TextDecorationType /Underline >> endobj 468 0 obj << /O /Layout /TextDecorationType /Underline >> endobj 469 0 obj << /O /Layout /TextDecorationType /Underline >> endobj 470 0 obj [ 189 0 R 190 0 R 191 0 R 192 0 R 193 0 R 194 0 R 195 0 R 196 0 R 197 0 R 198 0 R 199 0 R 200 0 R 201 0 R 202 0 R 204 0 R 205 0 R 206 0 R 207 0 R 208 0 R 209 0 R 210 0 R 212 0 R 214 0 R 216 0 R 218 0 R 220 0 R 222 0 R 224 0 R 226 0 R 227 0 R 228 0 R 229 0 R 231 0 R 232 0 R 233 0 R 234 0 R 235 0 R 236 0 R 237 0 R 239 0 R 240 0 R 241 0 R 243 0 R 245 0 R 247 0 R 248 0 R 250 0 R 251 0 R 252 0 R 253 0 R ] endobj 471 0 obj [ 255 0 R 257 0 R 258 0 R 261 0 R 263 0 R 265 0 R 266 0 R 268 0 R 270 0 R 271 0 R 272 0 R 273 0 R 274 0 R 275 0 R 276 0 R 278 0 R 280 0 R 281 0 R 283 0 R 285 0 R 287 0 R 289 0 R 291 0 R 293 0 R 295 0 R 296 0 R 297 0 R 298 0 R 299 0 R 300 0 R 301 0 R 302 0 R 303 0 R 304 0 R 305 0 R 306 0 R 307 0 R 308 0 R 309 0 R 310 0 R 311 0 R 313 0 R 315 0 R 317 0 R 319 0 R 322 0 R 324 0 R 325 0 R 326 0 R 327 0 R 328 0 R 329 0 R 330 0 R 331 0 R 332 0 R 334 0 R 335 0 R ] endobj 472 0 obj [ 335 0 R 336 0 R 337 0 R 338 0 R 339 0 R 340 0 R 341 0 R 342 0 R 343 0 R 344 0 R 346 0 R 347 0 R 348 0 R 349 0 R 350 0 R 352 0 R 354 0 R 356 0 R 357 0 R 358 0 R 360 0 R 361 0 R 362 0 R 363 0 R 364 0 R 365 0 R 366 0 R 367 0 R ] endobj 473 0 obj [ 367 0 R 370 0 R 371 0 R 373 0 R 375 0 R 376 0 R 377 0 R 378 0 R 380 0 R 382 0 R 384 0 R 386 0 R 388 0 R 390 0 R 392 0 R 394 0 R 396 0 R 397 0 R 399 0 R 401 0 R 403 0 R 405 0 R 406 0 R 408 0 R 410 0 R 412 0 R 414 0 R 416 0 R 417 0 R 418 0 R 419 0 R 420 0 R 422 0 R 424 0 R ] endobj 474 0 obj << /S /D >> endobj 475 0 obj << /Nums [ 0 474 0 R ] >> endobj 476 0 obj << /Producer (Acrobat Distiller 5.0 \(Windows\)) /Author (PC06702) /Creator (Acrobat PDFMaker 5.0 pour Word) /ModDate (D:20041022175708+03'00') /Title (\376\377\000D\000\351\000c\000i\000s\000i\000o\000n) /CreationDate (D:20041022175657+02'00') >> endobj 477 0 obj << /Type /Metadata /Subtype /XML /Length 1017 >> stream Décision endstream endobj 478 0 obj << /Type /Pages /Kids [ 482 0 R 1 0 R 4 0 R 7 0 R 10 0 R 13 0 R 16 0 R ] /Count 7 >> endobj xref 0 479 0000000000 65535 f 0000085867 00000 n 0000086226 00000 n 0000088604 00000 n 0000088625 00000 n 0000089028 00000 n 0000094808 00000 n 0000094829 00000 n 0000095201 00000 n 0000100383 00000 n 0000100404 00000 n 0000100808 00000 n 0000105535 00000 n 0000105557 00000 n 0000105976 00000 n 0000112013 00000 n 0000112035 00000 n 0000112410 00000 n 0000117589 00000 n 0000117611 00000 n 0000117791 00000 n 0000117984 00000 n 0000118181 00000 n 0000118334 00000 n 0000118518 00000 n 0000118723 00000 n 0000125892 00000 n 0000126112 00000 n 0000134844 00000 n 0000135070 00000 n 0000143854 00000 n 0000144059 00000 n 0000150720 00000 n 0000150944 00000 n 0000151170 00000 n 0000151473 00000 n 0000151536 00000 n 0000151714 00000 n 0000152043 00000 n 0000152401 00000 n 0000152758 00000 n 0000153131 00000 n 0000153504 00000 n 0000153877 00000 n 0000153956 00000 n 0000154658 00000 n 0000155199 00000 n 0000155350 00000 n 0000155429 00000 n 0000155550 00000 n 0000155645 00000 n 0000155796 00000 n 0000155891 00000 n 0000156048 00000 n 0000156143 00000 n 0000156238 00000 n 0000156333 00000 n 0000156508 00000 n 0000156620 00000 n 0000156773 00000 n 0000156824 00000 n 0000156977 00000 n 0000157090 00000 n 0000157181 00000 n 0000157305 00000 n 0000157418 00000 n 0000157583 00000 n 0000157634 00000 n 0000157761 00000 n 0000157812 00000 n 0000157896 00000 n 0000158009 00000 n 0000158060 00000 n 0000158173 00000 n 0000158224 00000 n 0000158337 00000 n 0000158388 00000 n 0000158499 00000 n 0000158587 00000 n 0000158700 00000 n 0000158751 00000 n 0000158864 00000 n 0000158915 00000 n 0000159028 00000 n 0000159079 00000 n 0000159192 00000 n 0000159243 00000 n 0000159356 00000 n 0000159407 00000 n 0000159485 00000 n 0000159578 00000 n 0000159731 00000 n 0000159832 00000 n 0000159933 00000 n 0000160084 00000 n 0000160212 00000 n 0000160269 00000 n 0000160420 00000 n 0000160548 00000 n 0000160605 00000 n 0000160734 00000 n 0000160792 00000 n 0000160922 00000 n 0000160980 00000 n 0000161056 00000 n 0000161132 00000 n 0000161244 00000 n 0000161296 00000 n 0000161373 00000 n 0000161450 00000 n 0000161544 00000 n 0000161638 00000 n 0000161790 00000 n 0000161878 00000 n 0000161954 00000 n 0000162108 00000 n 0000162184 00000 n 0000162272 00000 n 0000162353 00000 n 0000162429 00000 n 0000162517 00000 n 0000162598 00000 n 0000162675 00000 n 0000162764 00000 n 0000162846 00000 n 0000162923 00000 n 0000163012 00000 n 0000163094 00000 n 0000163171 00000 n 0000163260 00000 n 0000163342 00000 n 0000163419 00000 n 0000163508 00000 n 0000163590 00000 n 0000163667 00000 n 0000163756 00000 n 0000163838 00000 n 0000163915 00000 n 0000164004 00000 n 0000164086 00000 n 0000164163 00000 n 0000164252 00000 n 0000164334 00000 n 0000164411 00000 n 0000164500 00000 n 0000164582 00000 n 0000164659 00000 n 0000164748 00000 n 0000164830 00000 n 0000164907 00000 n 0000165004 00000 n 0000165086 00000 n 0000165168 00000 n 0000165245 00000 n 0000165334 00000 n 0000165416 00000 n 0000165493 00000 n 0000165600 00000 n 0000165658 00000 n 0000165740 00000 n 0000165835 00000 n 0000165893 00000 n 0000166000 00000 n 0000166058 00000 n 0000166140 00000 n 0000166235 00000 n 0000166293 00000 n 0000166424 00000 n 0000166492 00000 n 0000166648 00000 n 0000166779 00000 n 0000166847 00000 n 0000166942 00000 n 0000167019 00000 n 0000167096 00000 n 0000167173 00000 n 0000167250 00000 n 0000167345 00000 n 0000167440 00000 n 0000167541 00000 n 0000167630 00000 n 0000167783 00000 n 0000167878 00000 n 0000167976 00000 n 0000168071 00000 n 0000168146 00000 n 0000168241 00000 n 0000168339 00000 n 0000168416 00000 n 0000168493 00000 n 0000168569 00000 n 0000168645 00000 n 0000168739 00000 n 0000168815 00000 n 0000168891 00000 n 0000168967 00000 n 0000169043 00000 n 0000169119 00000 n 0000169195 00000 n 0000169271 00000 n 0000169348 00000 n 0000169425 00000 n 0000169502 00000 n 0000169613 00000 n 0000169672 00000 n 0000169761 00000 n 0000169838 00000 n 0000169915 00000 n 0000169992 00000 n 0000170069 00000 n 0000170146 00000 n 0000170277 00000 n 0000170345 00000 n 0000170476 00000 n 0000170544 00000 n 0000170675 00000 n 0000170743 00000 n 0000170855 00000 n 0000170949 00000 n 0000171080 00000 n 0000171170 00000 n 0000171282 00000 n 0000171395 00000 n 0000171526 00000 n 0000171616 00000 n 0000171728 00000 n 0000171814 00000 n 0000171903 00000 n 0000171998 00000 n 0000172093 00000 n 0000172224 00000 n 0000172277 00000 n 0000172366 00000 n 0000172461 00000 n 0000172556 00000 n 0000172651 00000 n 0000172728 00000 n 0000172805 00000 n 0000172900 00000 n 0000172957 00000 n 0000173036 00000 n 0000173133 00000 n 0000173246 00000 n 0000173298 00000 n 0000173401 00000 n 0000173514 00000 n 0000173607 00000 n 0000173686 00000 n 0000173763 00000 n 0000173858 00000 n 0000173916 00000 n 0000173993 00000 n 0000174070 00000 n 0000174147 00000 n 0000174242 00000 n 0000174300 00000 n 0000174395 00000 n 0000174453 00000 n 0000174564 00000 n 0000174659 00000 n 0000174813 00000 n 0000174871 00000 n 0000174974 00000 n 0000175087 00000 n 0000175180 00000 n 0000175259 00000 n 0000175338 00000 n 0000175433 00000 n 0000175491 00000 n 0000175586 00000 n 0000175644 00000 n 0000175721 00000 n 0000175798 00000 n 0000175876 00000 n 0000175954 00000 n 0000176032 00000 n 0000176110 00000 n 0000176206 00000 n 0000176264 00000 n 0000176360 00000 n 0000176418 00000 n 0000176496 00000 n 0000176608 00000 n 0000176667 00000 n 0000176779 00000 n 0000176838 00000 n 0000176950 00000 n 0000177009 00000 n 0000177121 00000 n 0000177180 00000 n 0000177292 00000 n 0000177351 00000 n 0000177463 00000 n 0000177522 00000 n 0000177634 00000 n 0000177693 00000 n 0000177789 00000 n 0000177867 00000 n 0000177945 00000 n 0000178023 00000 n 0000178101 00000 n 0000178179 00000 n 0000178257 00000 n 0000178335 00000 n 0000178413 00000 n 0000178491 00000 n 0000178569 00000 n 0000178647 00000 n 0000178725 00000 n 0000178803 00000 n 0000178881 00000 n 0000178959 00000 n 0000179053 00000 n 0000179131 00000 n 0000179225 00000 n 0000179303 00000 n 0000179398 00000 n 0000179498 00000 n 0000179594 00000 n 0000179671 00000 n 0000179772 00000 n 0000179872 00000 n 0000180024 00000 n 0000180118 00000 n 0000180196 00000 n 0000180274 00000 n 0000180370 00000 n 0000180466 00000 n 0000180562 00000 n 0000180658 00000 n 0000180754 00000 n 0000180850 00000 n 0000180946 00000 n 0000181048 00000 n 0000181106 00000 n 0000181186 00000 n 0000181304 00000 n 0000181381 00000 n 0000181458 00000 n 0000181535 00000 n 0000181612 00000 n 0000181707 00000 n 0000181784 00000 n 0000181861 00000 n 0000181938 00000 n 0000182039 00000 n 0000182128 00000 n 0000182224 00000 n 0000182320 00000 n 0000182416 00000 n 0000182494 00000 n 0000182596 00000 n 0000182685 00000 n 0000182781 00000 n 0000182839 00000 n 0000182935 00000 n 0000182993 00000 n 0000183071 00000 n 0000183149 00000 n 0000183251 00000 n 0000183309 00000 n 0000183387 00000 n 0000183465 00000 n 0000183543 00000 n 0000183621 00000 n 0000183699 00000 n 0000183795 00000 n 0000183873 00000 n 0000184015 00000 n 0000184073 00000 n 0000184225 00000 n 0000184304 00000 n 0000184399 00000 n 0000184457 00000 n 0000184552 00000 n 0000184610 00000 n 0000184705 00000 n 0000184800 00000 n 0000184895 00000 n 0000184990 00000 n 0000185048 00000 n 0000185143 00000 n 0000185201 00000 n 0000185296 00000 n 0000185354 00000 n 0000185450 00000 n 0000185508 00000 n 0000185604 00000 n 0000185662 00000 n 0000185758 00000 n 0000185816 00000 n 0000185912 00000 n 0000185970 00000 n 0000186066 00000 n 0000186124 00000 n 0000186220 00000 n 0000186278 00000 n 0000186358 00000 n 0000186454 00000 n 0000186512 00000 n 0000186608 00000 n 0000186666 00000 n 0000186762 00000 n 0000186820 00000 n 0000186932 00000 n 0000186990 00000 n 0000187086 00000 n 0000187182 00000 n 0000187240 00000 n 0000187336 00000 n 0000187394 00000 n 0000187490 00000 n 0000187548 00000 n 0000187644 00000 n 0000187702 00000 n 0000187798 00000 n 0000187856 00000 n 0000187936 00000 n 0000188016 00000 n 0000188112 00000 n 0000188208 00000 n 0000188320 00000 n 0000188378 00000 n 0000188490 00000 n 0000188548 00000 n 0000188660 00000 n 0000188718 00000 n 0000188841 00000 n 0000188993 00000 n 0000189148 00000 n 0000189497 00000 n 0000191266 00000 n 0000191342 00000 n 0000191399 00000 n 0000191456 00000 n 0000191513 00000 n 0000191581 00000 n 0000191638 00000 n 0000191695 00000 n 0000191763 00000 n 0000191820 00000 n 0000191877 00000 n 0000191945 00000 n 0000192002 00000 n 0000192059 00000 n 0000192122 00000 n 0000192210 00000 n 0000192305 00000 n 0000192412 00000 n 0000192652 00000 n 0000192707 00000 n 0000192836 00000 n 0000192971 00000 n 0000193085 00000 n 0000193644 00000 n 0000193713 00000 n 0000193782 00000 n 0000193851 00000 n 0000193920 00000 n 0000193989 00000 n 0000194058 00000 n 0000194127 00000 n 0000194196 00000 n 0000194265 00000 n 0000194334 00000 n 0000194403 00000 n 0000194472 00000 n 0000194541 00000 n 0000194610 00000 n 0000194679 00000 n 0000194748 00000 n 0000195177 00000 n 0000195663 00000 n 0000195913 00000 n 0000196212 00000 n 0000196244 00000 n 0000196290 00000 n 0000196557 00000 n 0000197659 00000 n trailer << /Size 479 /ID[<27b3c5f6320ffda39af6be5c7fb5d02c><2ab704bffce50a3f24f0af5287f8634a>] >> startxref 173 %%EOF vldocking_2.1.4/Licence_CeCILL-V1_VF.pdf0000644000175000017500000054257010573516344017532 0ustar twernertwerner%PDF-1.4 % 298 0 obj << /Linearized 1 /O 302 /H [ 1633 489 ] /L 181624 /E 98413 /N 7 /T 175545 >> endobj xref 298 40 0000000016 00000 n 0000001169 00000 n 0000001374 00000 n 0000001527 00000 n 0000002122 00000 n 0000002319 00000 n 0000002477 00000 n 0000002795 00000 n 0000002847 00000 n 0000002888 00000 n 0000003262 00000 n 0000003486 00000 n 0000003879 00000 n 0000004105 00000 n 0000004320 00000 n 0000004371 00000 n 0000004586 00000 n 0000004638 00000 n 0000006439 00000 n 0000006834 00000 n 0000007048 00000 n 0000007278 00000 n 0000008066 00000 n 0000008794 00000 n 0000009016 00000 n 0000009233 00000 n 0000018321 00000 n 0000018524 00000 n 0000018890 00000 n 0000027017 00000 n 0000027096 00000 n 0000041442 00000 n 0000059729 00000 n 0000076537 00000 n 0000079216 00000 n 0000091491 00000 n 0000094155 00000 n 0000095657 00000 n 0000001633 00000 n 0000002100 00000 n trailer << /Size 338 /Info 295 0 R /Encrypt 300 0 R /Root 299 0 R /Prev 175534 /ID[<9259eeec511b9ee72fbc2184871740b6>] >> startxref 0 %%EOF 299 0 obj << /Type /Catalog /Pages 296 0 R /Metadata 297 0 R /Outlines 36 0 R /StructTreeRoot 301 0 R /OpenAction [ 302 0 R /XYZ null null null ] /PageMode /UseNone /PageLabels 294 0 R >> endobj 300 0 obj << /Filter /Standard /R 2 /O (=Bۥ\(**툢&ϙ0>) /U (3h$u82Yhߜ) /P -28 /V 1 /Length 40 >> endobj 301 0 obj << /Type /StructTreeRoot /ParentTree 292 0 R /ParentTreeNextKey 8 /K [ 43 0 R ] >> endobj 336 0 obj << /S 267 /O 394 /L 410 /C 426 /Filter /FlateDecode /Length 337 0 R >> stream Әrg5p*q̔i/ޣ45ȧ= ^-߭GXD@|s+?썤UTY#Qj(j#2*ʮ_v͹*K ­W:pN*EB`ksWvzؘS9j66Ϳ-)]Br)s?q#w] xnYg[ endstream endobj 337 0 obj 359 endobj 302 0 obj << /Type /Page /Parent 296 0 R /Resources 304 0 R /Contents 315 0 R /Annots [ 303 0 R ] /StructParents 1 /MediaBox [ 0 0 595 842 ] /CropBox [ 0 0 595 842 ] /Rotate 0 >> endobj 303 0 obj << /Dest [ 302 0 R /XYZ 119 61 null ] /Type /Annot /Subtype /Link /Rect [ 245 404 250 414 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /H /O >> endobj 304 0 obj << /ProcSet [ /PDF /Text /ImageC /ImageI ] /Font << /TT2 310 0 R /TT4 309 0 R /TT6 307 0 R /TT8 316 0 R /TT10 319 0 R /TT12 320 0 R >> /XObject << /Im1 333 0 R /Im2 334 0 R /Im3 335 0 R >> /ExtGState << /GS1 327 0 R >> /ColorSpace << /Cs6 306 0 R /Cs8 305 0 R /Cs9 314 0 R /Cs10 312 0 R >> >> endobj 305 0 obj [ /Indexed 306 0 R 255 322 0 R ] endobj 306 0 obj [ /ICCBased 331 0 R ] endobj 307 0 obj << /Type /Font /Subtype /TrueType /FirstChar 32 /LastChar 101 /Widths [ 250 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 500 500 500 500 500 500 0 0 0 0 0 0 0 0 0 722 667 722 722 667 0 778 0 389 0 0 667 0 722 778 0 0 722 0 667 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 444 ] /Encoding /WinAnsiEncoding /BaseFont /GBEKFI+TimesNewRoman,Bold /FontDescriptor 308 0 R >> endobj 308 0 obj << /Type /FontDescriptor /Ascent 891 /CapHeight 656 /Descent -216 /Flags 34 /FontBBox [ -558 -307 2034 1026 ] /FontName /GBEKFI+TimesNewRoman,Bold /ItalicAngle 0 /StemV 160 /FontFile2 328 0 R >> endobj 309 0 obj << /Type /Font /Subtype /TrueType /FirstChar 32 /LastChar 117 /Widths [ 278 0 0 0 0 0 0 0 0 0 0 0 0 0 0 278 556 556 556 0 556 0 556 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 667 0 0 0 0 0 0 0 0 0 0 0 0 0 556 556 0 0 0 222 0 0 0 0 556 556 0 0 333 500 0 556 ] /Encoding /WinAnsiEncoding /BaseFont /GBEKEG+Arial,Italic /FontDescriptor 313 0 R >> endobj 310 0 obj << /Type /Font /Subtype /TrueType /FirstChar 32 /LastChar 49 /Widths [ 250 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 500 ] /Encoding /WinAnsiEncoding /BaseFont /GBEKAG+TimesNewRoman /FontDescriptor 311 0 R >> endobj 311 0 obj << /Type /FontDescriptor /Ascent 891 /CapHeight 0 /Descent -216 /Flags 34 /FontBBox [ -568 -307 2028 1007 ] /FontName /GBEKAG+TimesNewRoman /ItalicAngle 0 /StemV 0 /FontFile2 326 0 R >> endobj 312 0 obj [ /Indexed 306 0 R 93 325 0 R ] endobj 313 0 obj << /Type /FontDescriptor /Ascent 905 /CapHeight 0 /Descent -211 /Flags 96 /FontBBox [ -517 -325 1082 998 ] /FontName /GBEKEG+Arial,Italic /ItalicAngle -15 /StemV 0 /FontFile2 323 0 R >> endobj 314 0 obj [ /Indexed 306 0 R 255 324 0 R ] endobj 315 0 obj << /Length 1724 /Filter /FlateDecode >> stream v1Sq8kR̚x\zt` M`Ve8Z;w!b~s*I㇘.qv v14H80mH_%fxUeםQD/R!j Lsc\C,sÉ4`ȋU+0;<ꁍw7n~g]>,V]anVQ߂0,dJȾLW ޫv. _Ycujx2 fTGze.4^JWm^tRT1dʕ4#Xͭ$76?$)#NNHJ5i мIG /bE*XɏO9n9ڑ)2m4YmaBʎGua= q pR_TYic T zabӇɫ+:u&$锓Kw.p b"e#d| &U)/|qſ8yxx>RHQl+!-R[6bYdgȪC͐z ľJ'aJO~'4 mgP3NALcXyFfH`j{|ܯ!`펆v_q 3)c^Ʈ0_fE8cP5:ـ-Iu#UY:JA@9\*6pX'rIBR`O^Xj)x1Y,uVIn˷ខ7cY w`:{""s]uf!v\evՐ?4yKTAލ7%<-%W=V?}ɇu& yy! \gpL_m'¢'QaD8U_$]MEq>ϝOEɇ-P#B>bG~Lڵ︋8t\ĕ9%٬~@RȔP =qT [فm;b;.(E 7É^gsa5l"ugDK]z4>Fhe~l] lxbfҿ-?kftF B 5}ZlͶwE՗IDNiGAZɢ JQƋ\~dwzI dDMYDZV9iJlxhٌ 6A] 8dgڨY#Սk)1߼mOor:+*&gI ׇy{a;u ="z~=9,~Qi8` fRm, #s36R cr~c^}[Aq>ӌ)V{ gc? it6#- Spxxx;h2_ǸaiɈ#1b: b*pL;eL>fD /^Qv$ sTm Ob2QՙtqX&OӔ\\dogb^fL^J\DkxY3jvZ8*HZSk1i[ߡ fmkGdњ"tn˖{dnZY Xψl#H tЈQؐS1Oۣ" endstream endobj 316 0 obj << /Type /Font /Subtype /TrueType /FirstChar 32 /LastChar 118 /Widths [ 278 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 722 722 0 0 667 0 0 0 0 0 0 611 833 0 0 667 0 722 0 0 722 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 556 0 0 0 278 0 0 0 889 611 0 0 0 389 556 333 0 556 ] /Encoding /WinAnsiEncoding /BaseFont /GBEKHJ+Arial,Bold /FontDescriptor 317 0 R >> endobj 317 0 obj << /Type /FontDescriptor /Ascent 905 /CapHeight 0 /Descent -211 /Flags 32 /FontBBox [ -628 -376 2034 1010 ] /FontName /GBEKHJ+Arial,Bold /ItalicAngle 0 /StemV 133 /FontFile2 332 0 R >> endobj 318 0 obj << /Type /FontDescriptor /Ascent 935 /CapHeight 718 /Descent -211 /Flags 32 /FontBBox [ -182 -307 1000 1086 ] /FontName /GBEKLK+ArialNarrow /ItalicAngle 0 /StemV 78 /XHeight 515 /FontFile2 329 0 R >> endobj 319 0 obj << /Type /Font /Subtype /TrueType /FirstChar 32 /LastChar 251 /Widths [ 228 0 0 0 0 0 0 157 273 273 0 0 228 273 228 228 456 456 456 456 456 456 456 456 456 456 228 228 0 0 0 0 0 547 547 592 592 547 501 638 0 228 0 0 456 683 592 638 547 0 592 547 501 592 547 0 0 0 0 0 0 0 0 0 0 456 456 410 456 456 228 456 456 182 182 410 182 683 456 456 456 456 273 410 228 456 410 0 410 410 0 0 0 0 0 0 0 0 0 0 0 820 0 0 0 0 0 0 0 0 0 0 0 0 182 0 0 0 0 0 0 0 0 0 774 0 0 0 0 0 0 0 0 0 0 0 0 0 0 456 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 456 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 456 0 456 0 0 0 0 410 456 456 456 0 0 0 228 0 0 0 0 0 456 0 0 0 0 456 0 456 ] /Encoding /WinAnsiEncoding /BaseFont /GBEKLK+ArialNarrow /FontDescriptor 318 0 R >> endobj 320 0 obj << /Type /Font /Subtype /TrueType /FirstChar 32 /LastChar 233 /Widths [ 228 0 0 0 0 0 0 0 273 273 0 0 228 273 228 0 456 456 456 456 456 456 456 456 456 456 273 0 0 0 0 0 0 592 592 592 592 547 501 638 0 228 456 0 501 683 592 638 547 638 592 547 501 592 547 0 547 547 0 0 0 0 0 0 0 456 501 456 501 456 273 501 501 228 228 0 228 729 501 501 0 501 319 456 273 501 0 0 0 456 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 228 0 0 0 456 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 456 0 0 0 0 0 0 0 0 456 ] /Encoding /WinAnsiEncoding /BaseFont /GBEKOL+ArialNarrow-Bold /FontDescriptor 321 0 R >> endobj 321 0 obj << /Type /FontDescriptor /Ascent 935 /CapHeight 718 /Descent -211 /Flags 32 /FontBBox [ -137 -307 1000 1109 ] /FontName /GBEKOL+ArialNarrow-Bold /ItalicAngle 0 /StemV 118 /FontFile2 330 0 R >> endobj 322 0 obj << /Length 141 /Filter /FlateDecode >> stream ܴŔ(?ڟSs{`*^6[1̀t !Kd ^7~!<1&E@gYWJ1/p10ڝ!׈+拰7/AtU.TU«# endstream endobj 323 0 obj << /Filter /FlateDecode /Length 8996 /Length1 17536 >> stream tԼbc?S*ERV=V.ǟhCT?$90ӯ)au8<7 Q+Ѯ79V C UƠ4b47x 7Zv4)1;EX-9sH87&jh{4VIb:TB!4稵H3D);h"&hE-Wz+gy( o$2{ӳoá/2ޕX~Y)JVԅzO$5oPRٹeb\wPݓ+[ / xDNN]rkSҧ0qnPldvF9X)3l )Ն?Fxԁc`5x @>JYķ+jdf]^QICuqI@SrIC4*TCKu?E <=a_PH4'nac;[ \{TNo; 1׫51#`P0vWP*h⨜Vɻɖ9bƌEt%(l'(q[U5+^ 9* h"(TK2TdQ4Bp?Ub &^5l}". M Bfv`@|3G]6s su$2i?waൗWƟM7E1.CT)طRPMt ZV+ yq8B'{o$q͆p:r,X0J2ζrKMJrdTGr.:2CM.mO+W~f7~.?yi;B0eƖ+.z㣸cM19}*v-N(+dߪjh*z{ eKcSAlSYkkbFt[K v+y鴙=r꾗vKZ { ˂iJ{#X A)"]XrS(wלYkg0Μ V|3QsaMKDFX71>ik5s;<ώSف{:(<VJ&C͈`z6 u.M-e? >^ K2z]Ȅ9^4T9`2zOA؎ြ]ӎn, uRP:ŏ&LBH(Hқ82]<*P!(/iݓN]1x<76qrRT5&vGS`ОOPIPl.c 43/g7kO #!]8U>gDv+Ev2GU2' ?e;XH٠H25mW(4-x-"qnä`P3l[*[sn:/ gTٞb6ь)ʃ 3M"V%1kb_QL]cQ?LXN ҂]Eg'(=Yhnܙ=`̩3rr 5)/TY5ԫb@U)ViDo˭;9>E9AAt~˂sD=5"L>+m1 bh{/nWB`P!DtPLO/e(u7uawOɧ2(BčAh0A[ϲIu;)&-ܻ US] m$B/U(E^ w^{霡 "{>j(S <军E[c%ti s]SJߚw4A_&R{"BX *QQ3j$+J"yB0#FO6xcJD}m(C gmhC1IJ}aTp1GˊCgzk8Ɋrԫ/-FZdna]e1j=C{GIw}; j 1 oZK[̟eSHjYY*BGL~}:siбf@>}@I<#n ŧ/>ҼcWo ;$)0?|8[.gύLL=*N"Tc^%TټʚV6r2 9;M(g!iFJ e'fT'T.P7=\Y;-af~ LC1ZS]?X"\2hcm }Wj'b~֖E+7ZzfUʞWg!}5cp nkv F™#[I2U)~>9 ~KDI"[g>Րmz6(\ah#ZnOwQ+UCVג!_7?lJ|,HDe!KcE&*=4.b'G=z(oHԷYb~Bb*WD: w,_j x_37yZ!CcbnT!+3_)ЂD8K-Kϊ"o̸6o(V>R]D rbB@b9$G_ FweMhJ+FYt/CoWObүGG\ {ME%[D~M9W)#ZǢ#_u^-AـYAhu  x{mZ;. >/w W[ ,[s$[,… dZf:fc%!vfI.jy$%A UwejǗ I aG@mTa$@rfz|meYJ@p逺13Ax!TG@jC` q.=#kȯ< K>kY]H<'͆HD]ӯoZ,Qt8jZD2+.~A%U2;E̠5혲ֱ|@kAZeeJ'ՄfHhIT.2DtZ|-( \KXbiq7?rY&yEڈZ1!~V-^~^Cq?q".J[R ,(P}ki\Ds<^LʭLcW=Qr&C B]~ x\@j=RsJ?T}1ShGqY6k3^Cfwt{qyϝIsBNV0p!} *¡|͔̈́`RnJ?XiIb4 2it()~7d;vO! <'Qx[f|PX ,94M i,e *D:]ÌhMm;-h(@H6ve,ƫW۫vtj26z)' ZoRq>?^Z}7Dz'5-ɲԤ2-o2AlgsnSv}׼ ij)1]`# :f?*;= bNdcKf5# .7wFXutv`r:27" s+/vĜ\LkjPЕ= f4u͛NFG w,wY& P,5 )t E2T,KQ Ly6 S 03'`)oU_d&3O`e%|k yd,n7^JWh_+Sʷ\4l=XB&d-YC7vҁ5urHIr.>q7ӞgUw1S5? {OY֛JęQ6;ƭ]ڜMKYΈN{MLSSmkZ(e%EtuL 2JQFQn9BȝGg?v3kiHwI pΟb;uL3ws67*RbgN@ĈݞlVysA&!"XgG h̅V1Cz!!EmDPQhpg25Wgd~F_Dt2`YspQ ;ByF;C53Z:7oCQa]WHMճVS(Bg`q<%ECeʍdW56SzZhG'I%r,08[Bg#ٽSI-n"zy =昆\ 5 ^,)LՒEur* #Aq7Hv߄EW #=&; 8/'Q SQG5loz/*|ݘ85G3}_,4!g LP|YљYlNmr뜮Yn dC #h>WĄD6 wTkϛjZ6K>b63g>4PmͭbwD$"١ (rRf!n!gZ䆺 )kvu㘝4$rR β2P} =EF=d9/^uϐMr$Jt\YJٚrsNp)w .bb{ڵK %5B%Feߍjrxz#29Ok*§(/a<'+| vGGRP}zyT:k_q՞#02yMEMQӢw.R1rnV#9RQġlEm3Bɹ75~~>!x ŔO۽l"LdP+5I("*} zs]-<_o xٟ{{ÇVi54Ŧ;uMz\Ȳ3q&y74o㋉4OJI_'*6q%!XHʪ2rA(˱1Dz'eIv{uM0V?r$o$km;g7LÉ x:m5ƨ`z@mIrj\+yޓOj96#K е{yd{qlf,Vm8uMb*ThP 3(.J6h=kpy#p84NJu:vh:3uMdžן=Z{괟y}xcД{ʨ|+@[v_ XUim`AxSW^_S\@2qJ9JKnfhByV:`Ӝ)JjCLdMaC;} JL7-M| d^#©gw<٧,Q;OL|&IMb=H Ci*su6 jTx L&rQyeյn|#Z~4{-dUV&[69F;؏?j4y%jJRp^3 nn-  ԓ]Fw)z Z` c#| 9aռb *]~j5Fp)|ouӻ5I@>ޣ~=7MYU3z]tyƠ-N8۾p5a/U CsyGbK'OMlBuꐭͭb8X,ӜzԬ,jq]zb T`7Fh솺}|yN➚A/ (UeՋ>xf3I39꒮:.,}u&;Ah>B?q2}tvYi&Su]-QO#ީea1l0 ,`.j}XSlƇ"Br37eɶ,jhvt> %9̙?eb.uGM9_33ą1t@B7 yrʀr#.8n)Կ*Q \"ƑXmOOjvȕ**%hAm#}#2þo` ف!6s>*`ÏZFf _L0;Y1r”S @G=Q,ʕ7ӌ{nwuvU՝!sdƎ?^IZT+$3;Bx学B.=&W`3Ո7\'E0BPZ_jgoZV%YaeD$ A f˹=H%D>us˿1pfK~5\IWaϷwtl~:hLho/V"\,ܱ~֗mB)AᕻE֬ hy*h֎u,(8%Cdt~n{р(qKzozi^h  LheKofPI[FsղSi"K B\~?[7X/7:MK\:ҔB~櫓6HÁJV~!_fTNRl PqeވHW3tvlNnG=[KACA%:jقhWxbcUᑼkЕhiXE΀ɻ-,Kx?9mi9՟ p;(zuRQ3!1#Y iYc@ d%*bm%[[Kw^38hMI\dn޸0)kg nҞ{)2Țwn<`&Xq܆Rf VB"u*PHNZC88h=,qH UB~.31ܬ& ]g^jol9fV[$/~>L$FG) `ncFKLjwy$}ֹ vO"b\XEa=_.o :,G}PzZ^6FzrU[*-(Gq"}N=[O `Dx 30SU`*".=:r fZ^V15iAfe:KN0 3<0K,u? $CE`ƙՉiꐚ \K.hyR?kqfsW$ΟN{Ha'IoƗr3J/.]+ӕnoD/(B0LGYOt^):=.j1p?Z8yLQ[`%3 !jJEo QЍ paFxiWowB< IR(x«q'*A{X}d0oK2𦧛g*:uȼyuW.qZRqXWZP VkȳZ/ƺ0p+ ߼ bƊBjeI=aiU(۱yF%^EISoڽYc(|h:9l>V=ÄwL21s/ح@Pi#VyLSiP] U, EЗ19$EU.%'u-} 酇χrO={p&g #-tK)PbŗL1)#w+G:uMRn\iۖ7d0X\xcLۺ [GjFvX@NP$W endstream endobj 324 0 obj << /Length 127 /Filter /FlateDecode >> stream R|`*T28aAQO3[F+DuTLdiA̞9g %Em0QIYa+(ztm0rx8NGa `-Fs^7ʱAE endstream endobj 325 0 obj << /Length 290 /Filter /FlateDecode >> stream ݳպLM[V P ZGY8?~׀R?4w71VH8-I~k9ݩ}FVF7o݃K$m$_=qaReioMj7 Z5Qj#0> stream -L66Qo[HdNX(zV,ސ2Q W&ܯSkUe8Vì%VTf*}"V%ʦGGLw-'NE ~6lAOD\G5-\Qoc(ayܙG͙A"@+:Aa+\(ٛ<?>L+g$Km䘀;hyvVz5A4:7Rަ /hgLṳBw/ 2?"RwJz"n#83>s4s5"v$_XH tl9'd4i\7ZL3TWIc,_7FGn4J )=\-86V/!)IP[/՜lJ,g-z Atb-)o/NisU2װGIk n\Q%rIӪ i/ R#J=Й;,{f;T^Q"V$ʹCs'heՊ w6x. 0N' '6}({6sCy9iy_#[Y&Nvg%w oKXʩ0 0#覛wXQa4狃銴P'4MQUj_GIQKwCei&H YȮ3hyS#L_x' t?}.i7 dsRsZD4į-j/dc="}3v=ZROLVB^[c""al6v@ p:AQ:ܹzLFIy< Om<IKm[r$TeRq 1fE͇ {n}H{uT4Gk d >  ]B@RuWBL.:1qͬکnR\- &Kެ|QWmNRn^¯tjT%.}=&J.6D}Y -,LI) K cQEy!8Dq1n*<)}(}3{umW⟘0ڄ#Waؿ]5K F l;ojsj\p"M*.PBOh7Q_L ~܃3:4b݉V,͚oķz 6 fX#IZq(x:(T.j$B4xDfQìH`ցb;kpztɍ\W) rJ*@#R0PlO4#l;%l},@.(BC 4 Zh_$ T]sMW,HN yVn>L/c+s+b(ud𡦋Zתt!"Ǖ jB<&YS%z ^(TH9&s+t(rsHx!T?E S(*cO (pZ%#M":u1BU[Ҷ` {^?a<=CF, h\Ua~E3`c;J=phk2AYʄQt5 |D6G|q>Xn Ñ˫x¡ȍ 2գ.JjPVWe_rw`|s4/[ț}{^f"JO9W6Y8aǘp RZ;w6^7JܐXNda`i{9FѧTMbPv/]uL9+(CFZ UEk%2^E>uo'-qddQDrJNK; Df7Kq,a7v51{rwwPHx>juqMcCdN)29&$xũ`֠0P=z(Xhz1ȆL7mG FR.0D_7ba0 bʭ43뷡݄\W8q V‘[Ec(/(j]o VNvuz)W Z; )b:|9$s-HN|B9c?Jǀ Cb)Κ)膈S2! ᛟH7=xڠ>rÞykBid.2bY6,Ļ%)xqyWʊ = s|"I0eTfXq;-RȔJEzD\ pFS>|))C qw̭Nr9syD)ezƪcS gNi2[h UtZWQCT[ sŦQ ]t`B5 |ӯS!mqtpC>4dz(iÌ:ZӤ䋣Yρ>*6Ffs+wYfmF,}%EF(KQf6;nF5֔*_1‘q* r"8zi: O?R'qƯ*qԈ (olVgg.)ǮMFrs5÷mОI,֕hSܕ s^bf8~ #5 =Ԁ(a0 R"A *+̈́O S9%h #ØŶQ^)W}6M5eDN'NUvSꆓ'P*xi LUBK[+w쓌UMCs|@}!4MvlX`~IXZB9m-<-58d.~wG}.iۚvrk_(݃Q6Tq tցF~3;4qLQM'\&V-_C,OdJWʷZ&~SPJkW3 `ܩR={8{2E ~# )ꤴºTkJUҠEw o a"έy6)]QǶ2̋j-!re+hE]P>9PfӍ=f?[²HJqX/xM-@ H+d4>pfx{s@%Z/#zq-ީ("P#ޫ]^7!ǃU$ݚZWf!pUZ }m);qf`P3shC o<ټP[d\iD9bd>Smθ4UJsN$v2iNATQ{/$6Mb,(Uew%AF6soXӳ2:EvʼnKXR>Xj5@ޱ6R@Y) f=!̼L UlUp-H$=@淿Jd?{8EkZ,N*ШxD)%7^Of2Q116x^ gu"/y2&Ǜp/r%P,Ci姉_bCp2gIf^s$),p勞,7+F-u-UUADWB2YVs8HztBK%i.(},lW`@ӹP> %(%3!;NJot/,ː"ڴjAﵓ%"ˊFM?&$k ]||yϜ;A2#7.cGC7|?K_1/B[z* ~S};ƌl 4|F\&o=}i#kA IH_(–;^jw)As d7,Z]#O:Qp2w8Qn, )j<6&jWByAcWa+X61(ڰ wS$eN)! K@13 ډ!V{Q@6.Jy?{vP>z8&)3`"<|-?bQ #v *df?V.R)gBGcdz@AOG"=&\ 1H?RR@첌CvL<󓣁4Qs+ *%ޥQBAG,_nZz(,nR@Y?/F~lG#1 w MS'@|\}nUts5G2ٳqǐj-4" Z>G- -]Wxpv/ȭpt8}yK㾷?]~ ^vW4x=B4u۵Tle[6.${uf=T2b3)j& -6spFl,uCFgYϸ#y?*=ӣ |<$LT&]dyB>>6?!,0 V e HHZġMїfBXJ,Hmu;[&S^"SFv 0FEW\weOLIQ.Mdik)g/rԘ{M;PtZ_^A[r?/5TmbɅT #ϻa,4O2E-Bs#EW3?sފ}viw^C"ۑO $tVRw{H,xUB~ HW̍AhfQov0;3+Oj8bc;8/^w”:g\4 MnEaRdW2_l/ΏWM9P= 3Y#[p62m u~gv^N0V0 HOy|1s F Z^}'eӧī- :dy)ZgcT<Ӊ1бYm fJRbmANy;b[ b908b_/D[7`sp[ %$X(jVa`9SV0Zt+д\/aΪنJ2 mռ x{{x\Fɜ<`QG߹Z V >K}\ P9Z@ʣk\y鿤~`dc 6y|dPTׅYR-dq i'lns^%{MH 98m[NseC Mczg{K6~ (ת (o:67=>"VDb3䴣g bdoB1E(|`@< L!x5 hkmxثn3\nJ+\5ϖ.^kW=B2܆U9) GBp}RYc_T&m*Emk9&dxlNunW]]/ѹʰSPܼSx+/@9 S@G /|Eߞ`EY;2{$= ɸx,;_BuDRW3759 ‘)$:!x;gJ0 c&%^\Ϯ6&0m[x9Ar Q2sF͚ObѾp07 R}Wc :mS?~(~Չ0q:,} }'ljSk*G=}2C8잍'Ek(03@7/=U+nmjCr\ͣhD#m F%OSmwaҖÇ]!K4#AZXlG>페V73~䙥 endstream endobj 327 0 obj << /Type /ExtGState /SA false /SM 0.02 /TR2 /Default >> endobj 328 0 obj << /Filter /FlateDecode /Length 14253 /Length1 27296 >> stream #:%򼠃 K#E.а k/ih4-*pM2s浂vɮF#]HGj ֠kk,q+ eW{؊m)K=Ĵ^ {i%[MPYM0\W(h0F21-m`(1K!!gn ?c+~yAi@l?ѝqٗtoc2"N҅@lrtZKlH^RD>+L#belO}(THQn+DS.wz`&)}l,cCSԡ*VяfL_ U[:UҚ:6'/#?C+ svYd|w-ۗUrl3\ ۙ]:RVPUqJtQqP+Pdq ة4s~g$!tF~w%H47ٰ/"ţ.[;c[X]։CeAy=5`SO#{:Ls"z`eހZ {#-\$B0sV8i eZ6H8T1"'~.!gY`_j+7x*A zL^&Qn5YPi=Oqr`^pzn5zo/# Wrj&Nl#;sIO# (/qk#vCI騘~~] 8 _0ZYyYaT $1ikN:Fæ|'f6XZVE-,>I'wl̎PQh ?!;/n4v @#@si6%'FLV W(!4VJeval[|(>D[TKߊ+{&/P[ |C^FKr9qmD N#C+ [kU%qzy,%HǶX$˳ڵr t7zd7olLWsl]T}r0IM"Z@ G3`(}G~llx "72%_$xHČam:9?[uY M- O*疓j+;AAK,9Gq9݀J*qoŭկ[5Lr氀Z,) k(dCw(m, 3NtNNeB12E)Ìͥ[iɨF |;>.KjoLZKu/qlLܻv+UAh;[e_i 9s.kw/t%FzvQ& v % ݥ (nv rXү_/Klގ@l#ggö-(gWjO;O^_~WQX'r`DKWk4wC$Wyo{=ZL3qԃF9qr!7ŁdI}aWskjS|>ּ׋eǝT9/:zqԽŸkԱ%)םM FhLo֫!.C1qPĻ|`x l{{ N,w(8'bmFv5).Er;ۛ)_zr| u!O\mkd^E_h~U˨dj\]M caBj= $``JnySI{;XOHsr"A-cH%zXL @: z~8̫cI)6Ηdk3:( e[vX&G颤8^Q(E,JA 6b+C p CE;=dwu~7E`[pWeR-hD%}6GZ)r9zw^.kO.?hјqF!*"f073wV|AV&#f.ổ`Y~ny| !y}jn o'LnڈNuGRqz*TeJFr%? .@r ,ղ,i"vVh{Sq<̜zx0FR"F"!Oϵ%*J[D:SKtJ'B'xQqFq/7y.N`_4rR;A[.֓=e0]8%{93/ga&c!^b#tǵ9 tk(Snl_XqbDu'J:#`"vWBYay7kumww im #)udyZA)| R\_xK} , {6Ճ(D C>AYH}̋&w+-%6g~WwNq%eCAQ-p1b0*c4|[V Ojr3;" n4N^ܢ?ѡǤM?<7BW7ʆ̞]#ɘ7{fd^g.M*՚g)}3s3!s@KA "?L89aZdS h/ }s(jغ8LV1 nfqrc y`B @?w&l9!GtoE;@W-%?mVtMp1xB̿?îXQN 'Ŗ(V7!'w&bմdK),li2>X\k~aUgj@Ovq -  W X=مK swBU<9)-YQ\i'Q,$aFc^㢌l,/'!Qߍ#(Kr 27/J28 ja0>;._:4 b݉LsI.P[LEƕNX]V!iM&KFRcoֱg KJZOHrq}YfHrlVPъLܙNм$q23)t$Q{;-O:&I66gm_f]p:|Mْ3;ΎGÂ{n?ݘci*/ M2ecG!,h^{[K~AlVaDՋ0aՈq?Y8+lٳ<zudI[mAA k4XTFd,c7' .Dlj:rPOI,ttby3XMtR*sP䣟Sk+ "@GUw1Ӡ7hX,o WHЀ;tQdۺ] xٮ0A/ېfA|cȻG)~[b|$IO^S^QT<)fcW TX= JS$읖"R/aՋ(/`*Cw=|Mgu\{҂hW:Xk_+pl3 `frKJL3(e_U$t/؞tD.qQ<7?r4Ό> V2]Hsr龈KP(rei,e6f)+HA]xбLqyog2ݭˊ$EΒaZ(ߴuSw)"/B| G3۩4k,FZiTD>9~*Imڿ7zߚUkI~JTn !nLP3 I(I kmL&!j2ڞͷAԄp'd55%^uwͤH~+ AU$VFcNϿuNkUlϥQ ?{Z 2Ҳ_BAm,ѐ]#}Bnؠ&6QsH6xOVRq>B&`ܧRU KCh!h`yobz뗞%cXkKyw1XYB|<"^ե{J#9f7x;M_P>B.ϕIiP|HxQ@Q b,x4p< JnT!Pv0kl?Xȼ̐ⰾ$b ʼnjιY͛.t=& _@,4%)P[`Xy 7K$ZR}#%N+~Ɏ"& Jf&>0]B?0^dnT=7o[5W)$fKs!gD.)xG J&Kڥkgw>'dq݊_f)Ł8 &*R|5vb6xRxwݢ)rỲ~x} I'FlN:\ⱟڭ{װ~ŘBW8r,ŷ2ě\&Za>ijӮRȧ _+:}C߷2$ `ʹd G_vu1G}Dezl3K`UTf ʜt<8궗$`KwOkF_$])M\oQEbXT޵+-Buxst0 @rq-h)ێ /˝R&RX9sTcw+ I|HMZ5+T}zt~VS7rv3Z`Y\ kV6VV˥ xU¤\c_6|y[2Us3[0vp[F 6+$&T$g)!FL) fxV(Q 2RoH .]JX຅6ygZk":^ˌHfHy4EwIӭevar8enz}ɒØ0NBuV5%yTduv2?|FFTYO7L3؀W!K6KrE8+Wfhx.|#dpS?@!.~84^9IւMy##(oUCi]\MF/[1}h.+ #ڀ¼6> wZݭV{x>ةSdTvZ#- {i`H X@5ntlUNrkӁF,$![šnp^N[- "4FC]{)MG6bkHOTŃ4 G8^)y'atb@n<â»# 76uMPLۘn]|!_DhUx&d% t8%G]2m)* зkIf Ѩ\ƔKh.}ˎr[EO.m힋Ǜ(-'LwvN &vMG/bu1F$:ރv'Ks9*(\mE B%16 𡯱k‹iK7É;Cф|a)a- NNx0R1!]hLٰMT@XS D1\?~[sʣ!:C>yiݛJƽs5NZbp )י}ydb;^!-cN =vodCk/WW@̺p,d[T | nucWVoؓb+ {ʻWl>Kx/;wf_qioi\y #PwYJ_2QGVM4S">-[zrIg}_֢2K})%Q%: K #D^Cָ\ĨT(iE. CRwdEH+cmfOm.j!>Sྊ\(ȋIYU|(E_q>8n&PyuO'ac%h||,p7[Uu;wkkaQ 0Ubv}- c*|/ٟcowtDOl %ϑ$Uu[maH#QoTם`=5yZ}WtKH NCbǗ4$^^a $$\VR삥'WKW\nA jJyM6 ': ^h @—9kcBEE+q#yɝ@]%!/=ևӜMH) bQ15L`oŹvuj@E~ݧ)n8Q%D[sCkWxIv&(p -ms|F9!]Rm*{4/B%2+-^;@H`Múʜ&zfS]F>@lMϡTcA (\>/⮈읩Vf%Ao`(]&XO?eNACw/Թ#gLE9`AoL経[t^Vw KY#DWʫ(.l--,Xah 8Q9|`x!` 33x8e)X0jXVe ZDʃh^ǐⅻN1A8]R3?Op"Z[gYfvDc\Ț#iɖ|5sQ挟W^|ZN_3K'B4gz!O?N} =7*1 ٤҈g0v$G *G ϕ&&yp[x2->Ҩ$DO.*={v=8k8p[Ch@L?p`ɕ,֞"X Ȏ<#mv _U$jM,a>>+5My/=tȌDz.u>Zޠn]o4VpwR`4 C@8YKz@=|pd[Y\$>QPƫjȏi5NdQfU! y)6tHM 67#و8ہX;adF5C@NdT( ? /EkK 'cq. ~ކ 5V¬$qke1[A~ldkrox{>,Oq4@ʮ!E"X@GֈZā|̪J&%q7 -[Ioܝdp#=?{6}βTVcn'욅c$SS N bTP*p&s;<JQ9cږƧ5.^_*2ID5ߓ{ƒڃѺCb&Úa,Q'Q3n{m¢j2BkQ Ъ.@`̇?zIW +9|'!Lbqk>v@ ܗǁ?zq!y0eXe;huRH euSg`ׇNtoL*4)B6P[2WZ L[@0u\JY@ZLqzm͔2r\EA`ZC؍%p!(_~Z{xrFe4 `Iݟr BVfljUUҋ)\[-*"̅"U4rȨuk9~|VNz_zg}m_/˶ z/m +o_pRK͚R d G[TIvO:?m r "*Z$x(/Np1l{pǔ ֗U6pe%x*4 b^3x&'ER{< EB-ZtqV'.!0 m"~hMva.g]4Ql?}5ȥԵ-T䬅%QbWR\D@G sP5._goޖU$Bg;L;(Fn(?3=5'#dzpl0C-TjtQgRRrT%|6DKOQS5i 0`'@q`:™·c?qGrz'~3i,6E8i8LNw2(3˓itp qE~C/) C!Ar@rr b5dȔ$A7 4yyJs r+[>M}4VC2#=olv:NܣuקS*cCXjNоmHgcخ<ӂ, *`@($JTnixp`++r&{Ji!V9Q8 %< -n_qwEzLl&Ez }_W&9Mb1~r!߃OJb9Fk`_7x;ғ0qmy>`7 WٶÂYx&:1°Ԯ瞱Ɏ}Osvk{ȹ)ZI&6ENp>q&f+tCM¨c?ҍRJh34SOn-B9ܷ6tRܓ*=ӸfS:~?:<IU+uЂ6A2Ѩ W!q2?|M< ʹOL:6 TDuv:KKtâĠ(ÿ}QǪ$ߒZ8~, ;-n*o֓ۧ`"h65lA!3)72.N wo F|rGߕ20Zs梤-6һeK,ECU/ :]=̇ҟg}<%kCN l`g3naE/˭Fgx .l(>F=$3Ƴ럡ة0}n}e5{Rc!*`x% a}t OGt0II"jlCS4#TOϙ'1)y9!rX-fgTr]싀idv"[M-vMp|pE oMy+0){W1s[9ݻ!},z\)߹#ܤ97aEoBZ/. ߗсVcʴNcHX9 \!E1-ZǵKHkl+AK-khՎ@߮s4}HSC %x=Y檡+,YSq&yct8uEr+e_p-Ȝ6Ƚ:#2͏D9[!ذȞ)DNp W E N~X3Z ^w盧YBuΠ-l(Kd}hK!۫|g8:ǫsۖg鍓\{!DOPj_1V1n<RDm"50RNgZ=*{Y 6*rF:y/]ے'+S9}eVx:Rk.7=~OЛ#$B{w^0Rc[i;+Xm^.:,4@!y{ʴtܒ'~;&U5OVj} Rax"V ,^whW'.wTI nc+J܃Bq<8UFK /y(G8ܙ >-1u=#1EW.)SWIDhMY V%"ͶjnĊ(4 T(tn;KQOp+(vR,qa}2;h0h1ғ.KIqY=נȀ@@WsX*N!n沤|5Q6w<әKy+[Q?!!'nUt{iNघI|XksjO/t_4L\NymdSttRJkMw{$ߛVi||ЩՉ23޸{w~ S¿}>؆tQ8FjWv~aAJ, 2۔ߥgN ע$wu|,h`ǧ s+KAj> stream `ħ7f}gV.#Dq=*#Od)ۢa6+\= sOQ0`P;r/޸Y1g#ύ*3'*UN:uܟ=2Ru,.36𨰢_6<:9}X6θ@O#4iم5 {>s$V|#{R7)S?h BZBK]*EC7aEcb\g,fBNI8ݨ0zx7wh /\>xa50\IE/#+dK@1` 0]8,7 |Լ3TsigW+XT52 PSS +eu :{ xI|Ld۶輄sWСE=ʺW /,pi?PhQivX_^03jvx{'x9Arwċ%̰N=#w{Y]G2Q^Kk71jiMsk Xx$O`L?F9aG,>#賳&@Ұ6>wґGm}ei:KF0G|kNCZg _$T..~_27²Vn5Bh"L8=&s4K.K;g# v/ٛUI -j <~<^Ž! ,Xq{6?\Y썶[1@"'AJtJ(ӕCK'g* $<1\YM{o|x*P]1nsEܺ w~N?]5PoX;Z{^#Yk f 9Rq^`-FHRA:,Ry|kY ѡ~1 $($˶05Ao1k+KI'nia&ُ taa_s,(1ԏofvB֠F:5=e1ebDG!}4&(<4?U)"n0Vu= ^׃)q벤~4kdžebv:hGhoLE|YjV "Ls ;}Xe}lΛj|F"h*Ov|Z8*WTla?]PpQ4QmiN;"5:do6Y2z4 #){;.v/M6Iy5'} ڗ][Eqтe9tYG- Gb#_vGDyO ?#~y) tKrYʏUT/c>b>:͠1cTo0`F㤑=AZps!PM50M4L-㏆mM&OL'EiP[,|O85p}$h0ynj p 1Ifjka꒣J<),|/-]'?8^r?,Ϫʹ,ɴ]$>D9_w%+-1yQtά,AY>(k|?=Y9fی$`b:sӠ9L䢉 >lvrn",T4ySP/j)jQJޚ3e.lo[ Fls4 mw% 11Y̌R θ`0`!@kğW.&2+.cNӈ8,5Uݛv?g$O^xN;'E6]cqb,™ TXCd5349R3z'w)YⷠQMu֩#ga:jnGdg>>u!M >#)&~P*d|{ Hy4ݗH^Pdkmpz$!ܣ{@NN Q}&HK8{qx6aZ[_2<+yFI%q ^߱mwk8fB|< F$OlXSz.#dU3 BŘ>U8}K9Y{9/))Zc̿ -&M3/-$G>a8]oa4tr2*pja[ |SZ7!4zn̆ΎwhG P6xaA+و`43><䫞$;K s*L,3l+ ;G}w{= (JJ Tdy+FTHmGx0O>H}饋Nhvf2X9:jAO0:J]=Y["p`S*5_UDwW£éy`bϪ=SVO {oW7=7g:Di-wnTCDWZ?sRȣc_ZCt@h|{)E5P:(:邒0Sz=fl`V))Fwh҃ރ2)TnbϻW(u |zXs@^tsĵ7\I͇eteQnUhd'AP^9PS1飨,$^ v$FokʀBNZ,Wsڗ)K2EjWx&梁vZ&d<QwNt^HU}.Jeqzj{3;PAa5 `NF"Sh <ܬ-^X䦥)0+ǬAX/γ4ԔQN&NNMCzEpwYZLzVcY@Ng[ފBp.ـ9UglMUiZi$ NcXy=vu"!`R#<צhkS]߬>Yd_1z%m^Z9"}WL ʄ ZpJJtI|r@r \^{4Ɉ"6\ !e@i~ւz\cHhs6Mѕ k=eI`-K{rBjD&j# oWZg7x%f;Q 7MBaQ. ߒHMyM&Vl'Q:f Z mߜ)~E5գ|\Q_kܫ<  6 EƸ$9P~"k,~-A@^6UM!Բ…&o}XԪ0aP?E#F(ex B?(!@0|z*G^m2‚)N'BRH1/bdW'GDŽ1>L&EɊbe %e|G4cfbR#^ Lc hJ=Ą%GOtH9R TɰhHqJ )ts\x#I+eƫXV6|O>mf!- õ;b;9+0纐L7VˌhJ<)FeۻFXk 0U3jii}Kۛ68Oo5ۙ[̿&$bz/s=z+ e:Y;!J qcu(myb;_<=ʑg4J}@ZÌYaQ h]1ďw"U2$|އd @}[hS.pZK(y^ *ۀăp5݂9g4:ب>AhA M<-Xtjc]btubBX bUl; ZY^mƦX e.gRHqV\Gd,ڹ!{ xޏ[$;gVq#:gditep*MǡFZzqS5>>ATTd^l?ǯ8*(׿ҟ"_K/Ps]qWRLl.佩 /g@>L6iBa2C½Az085"CqtП.eʎ dN]E>|-Е;᪞А"}b'eIh6ٍԖZ\權/ ;*R=W\8Un81h&Kzrm#Bh~k@4H"PF義1Y^q+jJմ`Qݏ-PTwgMF7j.PbjN%5+*$B[H0a+$.)%K(So!3 .{ u{㧈,ߓپ-t+@ctOmTB) p_3UR~K>Hnߘl& iAZ"bA]xAn^O~D<{%^sQ(z(h}X'M_OHP:HorDlr+T/SO K:[ MZyBqJ=[JɞK}ӿ$c_Fi\6{󒞛,oG ~v!+@eG.w^9\QAU.$H!.֋}CrCҘY6T=IzGvy ,NM[/Aҳל5暍]%S8 9)\/jn ?8s̑׆1.`kɁtQyB_Q[T&|Wq;Ms(l/Г馔m#|xVI;5`,^iHd^:6a`5ҕ*)fkS[rChY~ڱ!PAnOH+nA{ &wB8@*KQL#;3*KG_g9k7,Ylb5:Zx0\"# +56}=`604nᚙ~k`ȍ -&.ɗHbpm_:Ҭq\#2pXYT?WUL"?&VXy*O _KT-%am"~Հ&9o4Hfknt<EH2\cma #>4 If4s|HrK"NZqߊGg^wcBwbE&`onSYOZd/<{3LOYOQ|&6^gǚzP s70-[DK1 .6V_'iYЛ-@}QK1:U$Hi=D3tNp|)bY(/DM}g"WUYPB_J̎L i 6VUX[Zb1 EuN j_~%AԎ(r [ޫ$ňsU߃k=-T2~kD7S7>ȁ`nR3qլH>/]Sx= Ek5` e-)$h (՗<0ħ+t6m8S&4yC&^]bC"'i]8.mp rFAnZP}Zdݨ' k$ݙc5iPPT\,ymI9#EQhy]Stۊ}(EV*~M%B z,]h9fSBŀ .)psjd,0ڟH4O*9t*yfG8ʹ]1Ρ24^B]ꂏrbdA,C`:A9ZEħð͆CE,HTC@yts\D~7i,.Cs pf9-|ˎ<rWW䤛dqx '!4ڻso`Bg>-f{1x[Vj|Śz\b^VEd i&7iM_gM>[ڄ: 8%vǶL l0\:䩑HZxUta-(ٻ#T Np 54rs-J9腺eGԶ *>׋]mUž \~k AM2U{dTk,J-LR8WW' Dҟ+FZHfԟdini@gi8MI\ğYd9@\Uh5'll_ώe.v jpv_]O[g gM'=RH vW~Z Wn!+I74m; aTD _elOP(}eUڟ:~ XcbkwEh*#ᳵio|j,c gP!=yCj c&8dBr:ulnxr.BmL煚1WB#mz"w;bKX/V7[(Fy%IS;6o8"^}1}Whd͇>=3m/CBgs͆Il$@?[-zc)Ez j/#X  IruKޝ'mEygA!y Ƚ ,ʉhhͫ es, s-h3Zrw<ΟOG^wNJ1umUTC{PYi_ފ侹N4*&ou3e/zE'bKɠ˴RGgp~ sv S91+."%7ln;ڀ{c  m M$z^X{jvfjcRNs~͚ $!(k 2OfQ)Pv/s:vFO?{Ri(w>Zp{/sy\dF3 V A&ɠ? R-OHdPe#> G -TvRIbE.˦Tsخj/؅)xEgT#)C '*v )eULV巌UBA"~wrMr"F)M~Ŕ q B@ -߂i$/7)@?SUe|t@r2?>:N9N؍40YzZ.2&xB$FƷU:Y7!b/OawoFp I2T" ڕ'Eͧ=@[2έ"-w6zh!_ PKLLjooalL_|@Hbs0N[G>Q#sAzh'XԎ]B >{ӎ):^,pwc5̓=$>;ۍY^ ?(HKV+{/,|jSEkaeBbҹKh ]Ik; ̰KU@QYy +#*W eD5.o[P\Em"aDH¼˲!CnvL +Kz1m9OіI`kQ%2Fã=aam>!_)~Hg4|vF^*۩C #-M'G-{[^N2AV=(gP^gO(Z.⚼ MT݋{!ҊgOҲ<5T }0MFGC&ay'W 4JVз!Q~ts៧%٣ǂĢCյ޹$"]72*'Pp7땒2ZM[1E6(E*[+gnG/R:]lDð,h^ڣ 쬠ݥח& +FƼ.>B^y@1dԘvF-`FQ<8tiM3 N2z1~DB eiV~t_ϔW ޳M빷UuۖCjT)Q=A9GVu`{X+e#'Zڥf3]ܓJ`;f9af!yT}TzGM zY9zmCǨ\Zv++|~K釼5"_)W3,8"AGD8ѣנdw`>)UnjS&Ky WXX7 L-P5 -Y"}PcxȲWNv&ۧ:Bj`VIسiܗ>Û |?b"ISJľ,`W+d{h `;oI]Ҡ^P;ybxFJ>4Je-aYT>2fgZ^[z3pDb+:5nm5lݳZao[ЃK"߄S]%`xYrZ;m:n?zNg$ŧp/jo3BZ{;632̅vt">SdU;կݯptZ=M " M ;sv o%A xXzQ4J9r5rIǀS5\A5vdHv6qV*P ݔ.fv(@\+ 8JR 7k3KA.* Q3D(є|662XtG{L\[Mg.3Rw9h%\j G=P:ji݀LB/9ɼ%@¥ޛ!W..:<{ɫ*gf,C*~/½$&2se'et#8#gax>mD|{Fl>S{;wp#5d>oāXhY‰'LM?b$?;b -ζ׎ z!fʇ7z^ˠ86JC^~u,7&<2q䧒J; mIVau 7K\{*b(EA/EM܁h6 ְHAf| Džw+h$?* P# Wpֆf,1}U? ;A7[z3s ['R{H6/H7 8a$A乺M>;P^w%.$8I\HDw%>_[q?<봠 cfʛxreۑw-!_sS )_Im!xi,J vy3\Bu!ŃHiՇέ5?ҩY`LCso\k=9wuNoCS k$8 Z{SNZߣף0Q޴]n-=%0om:Fn](8]6t"學Q?:7?'PBSn8Ӳ&@0vFƅizZS1T8 =NW-(ݝ;k~؃*gQ0zW0C޹躔R77Kn /zXNOoM?ks}a|!S2fQx nZ1]4@+\=G4+ ͤrLw&,oVM)C:FHQB *1^ S+(??z%3cU/NΙUFT%(*U#S $^vJ%j`6+. tbS RXk*P:i&JZJȯ$A8y6FSF3><1nD4蒛zͅWzKA0^b~6w,~ʸ3͋rn yS[/2ه[㓺)ɉuΘ-ȫ+0*kZ0wrUǑΰ ,rԿ'^L<\q9'9 wgo*.]7~!6CFO1cOy9u*3q;;ֶeXA[h}uxΟ#6B34ѪA&4{EpCbQmvBf!<+)'?z<5ݲq QphNB,6kDµ:O#73Q7?8R^i(Q-ne*ぞjJ9He>t.p:ue󣄖J5`n7ܬ,CsZ*لMPu'#f#Kkc=7EeS7^ަDy/0F5I|lGA".&R,7ܻ!- !1x0xcBf /FӴ[I;|ʌ\W׊8Nb#qPa]u==ɔy&#;Sn[o$Grڋ%fgEPU``>~yC9c S0ѧYɀHZTO|tN`j+p\2rusJEGMNSUe3(?Yj|o.t4Ff!9ɔڲ+~'^HwlJ\пX̪Z3^BzX%٧yP- nX??O]ԹZBߢNf-=N]d7|^ ,l HuUmS;,ߛ)%"vDZCQQ͕tAЂYHBh֏gk tr_$SUW176G%A'xrsǦTѦʾ|SˉRX Z8W4x~NP:+1͒;geo7GBzF,RG3(QUt'qbHLd S3Mh _jɀRlޘ}&{x,>2NxhEHK'AMmp5 c*_ii@}3տX+EJHѶT#AkvNs 2h*F9Z1|_hA;/cycEhz'p*0Jϩ<ɍx.*z!kk=[yGQ#sFC08'hϥ?fF?kݍɤ!ZV;qYծ acBzR888r!y ܃hm o86>E\o&P$Sap֔p8v<0Pox$o @\MZ1_- ȓ>s)BV7`-ٖTTަ0MћkXԦpDJpD1 ΄4%F78=2RZpRG^Қ-iREOdT-#Kl^j RFՒd=f|;1džm,Kd 9 jNАY=7֧G:(hLֵabԽȋEOٿZ52Ӈ0;׻Bbi]3Znn9T(I#' Զ* Ac"ۺ_Kj&S?*GVW? ;F(Z*T9r>MC^3g ''u1Hkk\VX=E6@~Y6N{S/FM zzXNl,S{΢pD+fP] b4$FL ??~OwLSSvSD[ S Z^FU[8VT \gp1eJIXhHڗY"}Ɏ-D0~ +ؙЌd/Am3W!ZmLzDc GoH|)sk]oNWa3%3O! 5eA\te&, a]1~•0P j/(ыe_[/~JO|ԉ/)Ս]ޅrg&KkB;i!>>#NKBڱZ3guh{yqGMJ0* (5$1"DŷjEdTWbd+]ZC;Н]ի+|u9m|̇긩OO)#k8c+!ujz b'hcwvL2kTtYli&t\,@ӚlV)y7{{A^"*u2OTS;bM@=iS$gV6FX.VDΨA79_1:˜\.rl>mlD}Ա2!SZN6qn;h.:odڒq0`Jw_Ej nxD-e R Qwvf=ر*|*Q^xWco`}nl~f qG!E9tn=9%#Ӄ-GIF Yj$*1+k onu0n2\!13Yc~Vl؜SPZg|n,q^ P~+DS $-0cv: na4=D! GS x.8ZikA<0xc v 9H#OksI3DwA$ gi]+dD4 \38SE5CzB%ik'`F:GI*Gq Pu@NWyc C:?"d i n 2 0@ j>8hd8WX_qT$ݒsUۈJ4.\%*߰XIYEˬt_9w(Њ;gPl2g'A|+#rK&'mcE8Ql^=(abl+@Ԥ;i!8 3TnxUw-*&z_ u2M|[m'i?bIБwҏLNwh ɒ31$g9x.p]P]okQ*h,_ yԓ"E%ɗJ`m|]VH*u2ĶElѺLi &+HoAM > : 2g)jr4)^$Ɋ\m 7\fiFzD\,$R}jouob"@ޮ-$Ŭ k>y[I@ܭy`e_͏8ӈ#DǛ8$ z"z/x${`oy n D9^ku:09[L UVꍸ9l)cG/YW8 1*"Uew}>w:gWOa_ȱtjyBi!h#:Ofqlw=6VX`24Qur=M͞M8߶ endstream endobj 330 0 obj << /Filter /FlateDecode /Length 16715 /Length1 24172 >> stream ?[Z*40 xxyԮiӆy ;E9rv<{Y1 h5ǵrHᦽlإ4y!O_&d4K OzZa:2צCaM3k'؃yr㩓PFGEdg:VH\K`(txAE%^}i7oALq23Wh{o qWdշ< R"v[:/|"q j%='y[91TTyOLBH/ޫKJ-{5JtsJ! P'I.8@Ω=ٳR)JX6nu%BT:Ȋp#L2"nζzg'q 28?Wx2OW5;ua~E*۽I$+5$Z6/FCEƲa('z(x4~FnjLUo㛦U Hj | -#;:^wV?1EX%u> ۦ>~9{폲"d%́uN =dHo>p+ Yr)6$gKWj ]= Iυ-gkgOl&f쟫Պv2Gh1ʍ\;=E&=)a}j@KEf8g3΂xЙDԏK$wF6/PC.UZZ6S;:%#k㫘B0Ee8PK/˟$4Y-&:ǀRhY؜gd*?Q:kB}P}ފC5'QRT8>ɍ8gҢmٟЦI6!|>] Naĝ#(`+H/9_zn(ttKثG}8.BnXD~&ryg:tfw0u_J! {!$EҸ$m'8j U'HWf|\jS%$y'z>Wc$W@F*pñwwx,!%3Mf QT0 kHB3LVZuٝ*Yc?҃vYtdwo>2pޏ[sJI=n3~>=.ܛQ(ė0CGy%XR%ёe (tѫ b|M5HvUjp!$sOP +#)D3Ǥ$z7NLftd]T Q 1ʾ6®+I[:+y6 r1*/l&^,.{<,Th ]xm'^ݴ޼c(V|bu$Lv4EGvvj ̌3udTX{4Pg)Uɖtܗ ͫfp]C?J׎;#'Oa,X)G^(/UNǁ!C:2Z('!dZb`Bgc7/ ,نY}qRҘWuItqt" vnWN&X>h,G loj;ur ͽWCAG5Ɍ]ڱ/E0.ϵ<3֩H^bUv2fꒆ?Ӛ i͆;_[,#2>R#%ڒr/V ]YN65㲃¢aG,1[p-tbGxKQ4ΰ?0{=|)*Ceq4xCU V8T!z䛒zxqUpTcN ?R!-.m1æHؼ}p@ԗR&Q%*5f-Yagۮ@ՔѦ'&8EjLDfɋ-20{V%)fl@f,A@`UaDO8qպnέwWŝa:;,rDf FV@U1OEj)L`eIҩE[@㉳읭ĉX *:Ixc?&5Mú%')AfSJ/$5kdz`3B^rV*= 7dT՘,hH?bba2ZC;5dpc_:- wrS>l]oQ54AmER\$ڽ35] H<8QDǧ4JRQp96K+]E,(@`?D/F4w#Fdy#MPFR"kۃL˴+C VaRx^O7=LXPX9:ݴU:l` WË @)b PAlp |_(F͹ݪ+|s YgA; Cy-og7S62M ]j(ظkeB}z2&%6zۓ@#zxj}{lv5Ć㙠V%`E $m![K{ܸZU8y2d$3ܥTR+z}[t ~ּf&kuNfј%6tvf}OƸts,;W@ P7UDV>X0gTZ ÝUIK/5/})J\H]O/$'L Y~'0F6I!(@ud X,>̅^MewAsqE B=Tาgp>]KaSF#gz Ϥ%TV|2" KZh'r.h 2 |BHw|Y}a_v:0W7fm`B}ǐjׂ(vYN 7Yݠ5fPNW<ڑ[cmۀ:RBdu ^*6_:G\-\:0ËdTRu0&܅ !.;#^-(ѪzJ\נZWKr?\!i&xr;?=VUti!TJjy+sRzВRsw)=o6>a8lWbg'@p5Ww8u |}3o;"|[OH\~8zԂ\p.6uӃ__ȑF$ArرuZ%Lxf 9F*p,jrR`bsW}V>?4)OHCŷ 43az{5sch?N&A8<Y* }S{]"Z{;l[ǣi3{ S"6I(^XCahV#OKiAcӂv~m6 sjPm9z} cy7j(fǪ=ajVom)RKtZJ3 )b}(KN\&Р7 foyU&A\I8D/_}٭6ODDB9Va.pbBiϑ2k+OiwYZC?=Mcv*9HRlP۔8鲵o-kE:ޘt.A vm*11IJ>l V)!;|P ynx>G·)pxחҕn=A} LU1iOص#H)/WLk@ —t;-TۜeӖϕ z> /4+4/a?!T/k6 FcǞ gpz\ _uY؅*Nហx{LCB89=6f$>3ȉ7 {-3mM3ҫ]@Xt{{ԙ.gE9Bf`[WE~5 ;rt`X,M%{3RG07 Â+5wk*E\jm?|Ŗg{>v*~ f D]bM8D *z y郲WHIAf"F\t| i {RHT褽d4?K4fźEܫKo1`'E֜1-b<'0_xZDwfu#R<2~XF|~R/Y?YJT[ ,+Iv󎆻׿ɓO7% >QTj]7Rዩ=2L0v5ބ| Q}u,֧Қ̮AG*r v!FRHs\&ȹ65Aۄ3;oN҅]Tϑ+u>ע+5XꯒPf)YJǿm_iFI:.:B"EEd4mړΖX9;WTڝY#?ԇ@+Tk O B.)P}x"+IjOZ>LϹV ONJy YWŎjʓʐߎB J ŗj'cV@j)|,FMu5ZV`@a, =(r+87R[ZՒ#lF _{'EqJȾB~(Cրv`㈱7y MzK u'Ek687Ĵc\?Q֣u~Dd\8ɐ;ј_'-:-_M)5)Kz ` E֍!j|{,#z} 3{ec[l[1>w2_|ÿ#w@3/#eEy`H]Exw4ro'K1=< 6)e'хsuәs~,hصTwfP떅5 #k1:'gg78dVw F>sn:0Tǥ}ae 1JG!<3z ׁF٩.u؊HAe&wHn%$TXAlpMIǻFw'ВɧY=76bZ|\Sոk]v94<L)_JSoI'uZ՛Dw=U,AXvpƹ?E\a*%XlCy Вܾޘd*^TrS6 P\h Z3ruم.%&/%ԮaB@v+NLVqyKMDXO 'j 3%7F{ 3F-zo~Ꞅne"h+ j(L ,UK11r}HxbK4C- "=whcSC%7TU E\ ?@s =nwXI.84m$}=%1b$VU굁gNQJ0,.|Hy jy]4Ff ZYB|VBr4tOfPzř RpPL_ydKѻƛ?m@o(Jk_̀[I4`绸 ONِ"6ẇ0A(Ǽ?`yr )ה"US盦\WN-7-pЮPG(6DzCwJ{A~@%T;1Chü^[ r;s1J"=|B0Ȋ)_6# 6  2]csXBI_Գg>FajZ#6Q~Nj*/G/K]p_Q[`*Yr$ \@VNhiN|)"7tG} Dw ˧54 t'{@2kݷK-@bQ&m)R/3!juܘ L 餉#KiB,&<)Yyе򯱼km4U2:ԕKԔ:(Ǚ@,B,vx[Y*/ǧ8# T$G3y xAwD1Ydf ի6`ѝkywSBpAg} ׅU6sI!+]PP|yD=:>-.1TWf17"x z뚖R_t5t|3Nmv!VN|K *XM<[G!ߏ| š8DkRl:DS<}oXɆA4Pˊ>a c: !J=c0VS~w Fȑh .W=бƾ:^D^XwۄA6 4 *`ϦnI #+rZڧh|BEU PY1X?3WB'; IԠ\r55x5kCWZ0ms U!Hn~h\ةG Eeg ]=&SV I,45 O蒁/ T=`[f$eo"9T*s{}Eܩxez}ׂ$U]xߠ߹CZD K&:iR$mu\deËi5Va }'%8Byb3//ѯIt4t; :ph/7z %͟6|f& DFm8xJRDpkiOmrn;2;m,TYc^]m:.60L'M\U,e h#"]+Qvʦ}2IUb9!xY{:*evs|,WqnKLE3̀CekXaXA].PG}\~nw +DS#°- R(_݉9 ZR?;nڣ)?(}@h>OBKu_y}1IŔ/emJa Kirhg ]AXͤ)iCnZ`kMO^Ĥ%"5A/MWjkvϦG;lhsLj'ƻi cP"q{; c'NIeUW֋ۭD4Ȩfj?aVJazC)JմGwx~bzI sK!u.|| Yx=eV0{`ɉMOv3F%q" V:5m>XQM%pʙUu h|Q]ESn)5Q>9Ҩigrb=pC/ܭf-qhevo/فC ^3^db $w8&k>-lg [jvXơ?Ne<[`%kZz0x˪^DzM:cK' QbbjfIз &RSy ~<"ajF[CR5R鮘G+v}d{mD׹X8| ymsy _|riٯK Q"Yx!SEN}S’֟Hؤ32ӧY3cނ  8Tlo &Aytcu q8#AS:1NB$AK^ɏ!ri6d= D3c S-v:F˃? { S܄%YEg?"ߥ~ _j7& ANP//сJN6 {m;18|#Ԧ/joL|!!K AyxpZ=.j[;#7-Xu! ;F@QyoˌY ~^DV-B" ޴CGxX\oq{kץr GqU] 8賅V^;[A RcvYO/\IC} MM1@tHl5kaӢŃݔZۤ=6G3pķswVX zc2KRma 3ͣ0X  ņ]^sKcr4M-}NC}+oE Ji(vI{Q?+; 0ۅ-XW}tC6Q▄gIDDnQ9ԩx obT2bVF-Ni8*/m0şSL1jC+SʡD|ZjIe*t׌UfDtŠ-"'%d|O` ZWMuGW^/ ZP Xm]7HGv R͗sVVXk>lJw}ΚlY ^ncSwZ:#_Ms`V*EIW- <*20bLaVĪR:p3#7,pɏUFEV=E֨GvUGHפeNR/Qzc0D4^oIh?\pl KTe!22^1No֖AcP@-}1.SlGɜ9Y-)7FA&%ˌhAvpD}WY4aE);փpS(Z s@x@ZM^<8'o8r8דo ˥zzRgB:\_X _ȨI'RIj x]M5R64Pq-h(YT/油TdZ+1/Z=s=#kŰBpl_'tQAn՟N +R>?xV *MWw BTAG7Ua䇎vf*Z8-WyW-:  ),*KW/ߔ 1 r0CKhpVnr` d1{7-U[&@ &nM2c7=r.IƴlO\jCQq(%V.8&!ë[' z L:qBlEyB777)qwYMvb$Wč!7?exsq9ȕ(Km?+kU%L zvYet(Z'8ޟ{iM $t2Q\ 2OJx #q@J݇ԄT2P/W1a6{#_:.𣇡D/?#wGOÈNI͐h] E*^m}\#B*N-/y]_H\2ڀhotZ/qNHDR}WN~BrR[lU.>VrT~$<\9F%IZ qɮ`a—MTE4 2 `yϭ85uP߅C,w&mxZ{A-?nJƣ \U Hsr_5nfR # "Kh^oa]NlXжjG%nfU Hԅgt.)E 6|S'd݅'kɧ3q'U}J|D+IhE>c4I.Ow/Mw?9D۰<ލC$c1.F~!Rp$~${hѝ[9xH #ȯ-4 f\tGkRJq+MH۾K\=Db)" t6쳈=$ًUUo̞'~zk^R)Z3q%q!w]!`oa|ϢÁ2-ӫ\ v&6X>,{Xyal44XR1F7鯉y$ŒK*[s3'Em;rZo'1D#~'eHL|f9&QMLT C#؋YXu,W˿OfkϳVf1)Y-Q3ssZEِf"˹J0Ձ.N\kw-i _:>7pR(3e״$4~}3e4t55ȉXDJsA~!,#ѓ) mFgc3Y -`1^"XzY~pEu~* F?N/\&U/z:9Qxiӹ @i?ϧ.;E܄5og/kE훦H1«cIaaٌGlPNde ѣ8!B* Ȳ7W`{n wXA~(Ns8c$}ʐy~{ qwK}8sWqwMc/Z=bҹz[?>["zHs|x*3lVD銶p,&=%ath|MO@cs_ocճ :ոCT3=fXp!ҫF쬿^M$ILQ_7c_b7dyIjB0޽W-f$aEYEY[Ps,A[;E!uJ(8l;c/ Sq` S 6'eu ɡƅRPXe0 z-|F?JM^:KP;Gp<\`u Xphc=7_ĎGmFFCR(S['``+y0[`J荅qL"3 _D՜o؊44 AGAJus'?bhI7)3<%Y ?[vȦ!0ߛsgWwRX ٽWQXXkdAc ]q$Z`'<&O;O>'"i 4O 3G[RygҤJp  E4+|6 dKkɆ}[yQ++x_V %f im/TWqD ?XT"V}}?홉 rbfdPeVtɨ}RTtL Pf ^U0{ S>'r\ˀ=/xֶӗ:PIiCCw0l ڥCՄhz #m梪pښH+Zq"B@1o{F整\6- Q2EsZWl'rw"\F0(=ϯ3f@,#2oi|g^ksۦ(fqNzCe7O`V $GĔ?ʴ`sȳwvѐ`|~0Dߖ _RP??`ԚHOlr}AreUK2DxsWPG(^u;+,n}fDG޳/2e9I\3f,kt\<жyaM.7% ci$rwZ A,<Ή2K>A{^L{ eCgJþfr:Rm3㵫j5[-87*xr |s{#&YT0ښZLP j_ObASNe \%ʕbb,\~uPGLqCaһlT^U(I h=8ܩR٣o4KT,db͙˾F]p&@RPΈbyd<|T1JJVT/lCHd5FhZY$"@Sb%t.>ZD.f*|Crк6yCL|Lǝb?(<uAjS| Zuɩ1y(OJ@"ieW;΅݋pXMЁaʇ%zr/WDK9.jϩw+sY 1mr:~#xUСFvPEgس[D:e}U!m?|Ɏ$h4UTגHLL K, 4/rf;I4p*x3<<, "e/yQC)@qb1SW3m׹g~vY[ج1?]Cp7l PpeLGY쬝{Cr@[Ӫߝ|nf@9K`m(/ V瑵cu~^9MP.C4hSc2H3I!GOѪD$' -쪢qIZ糘C}wu nSb!)ff'E|aIͳPx[' mRLo8brW(BBl=Tt^zv680(= SFt0Ʒ-;׸Z@9KuZ#'%9\d6IkFb9(#H> UGE8VYLuM+2/IUl3LTPvXK $fst ho[6ι;.׿V*[ӳl+' RbU$="vޣ+iK8T?\Si >(C  nX[%xY'J04`'sHdwbkO/v7GHO;&]Ց1&YAەQͺ4-&­&*uUwVHO އ˺6uOT#Q <׊ȁiܮ*jsf3D?P9~m:^, ϓ:g?K_;ͮaHkr/#ʀϚ +#56 R4<EX{SE[9o6*srHd6x] Uث/㡏 Bt9$uNVz[OZdJeW&F~JaP1@X.@srz[N(ղdvB}I"7$U/ HN6vR(7@'ptg "dW20_c{DB_k~օYJ dw \VQ&HsmI VyK*}[{jw Z(mL?bZBniM6+r'{]y1;p{~x{!ZD[72뙱{ JS1n3v[iWAI. ƳIı]B=0{F-UcAIkJe#Vuqkx7VhՑ GB(,W#݂JIhi4K~!Eyٟy|"o߂zO>lKD{p|f#DՒ3$ ܈gKb}llo{aio endstream endobj 331 0 obj << /N 3 /Alternate /DeviceRGB /Length 2575 /Filter /FlateDecode >> stream ـTL@kuiAf{1(mzK@twț#8;ׯs h}S{z K=9aQv4i=~#m N f[njR5ûojGf&p9"xQbLMk[*lYr+Qj&sB ;lB4>hI/^@pDoPXc+t!(pcжЦT_BtH@Č}c".EPݣbì@cD)5r8r6@> !=7L&_.r k-),vuEI4j8 ۛsjFf߾{@SU())u@p1nP^ $%[%,N"R&[աiLtG.ނ=rios6Z/T^ L | \4 ة{ %װ ncBb! Q'b&;ݹ][RSne.x:M5Lm^~:>?J]: 5D37]E-zt)~k)CwZE*;r'$6*$) *~ڭ/S;Byi}6=p]StvQ &=vNpȌTK(l+B^N&- B15o@Ux5_:kB1x(Fq=7 ͸a3Pژ` `p"F k'HPu U ;\7S.U{!󕰸6z5jo0)re{HP<ٴl_*v/2yg€rA#wT[1']`a% M4G)NmAe ޯ"Het( C)ݰ-?;Pb)KjOU]@1kD&R0wpqaHOVxaCDHPk8m$4m~i% ]6AUO]mBYr~γ-x6A; `Fy΀ S"禮@ճ~F`Z$t"PzVu\xU1IC x1@*BW@'ޥ}{NK7yN:C̻4!&{)w~]aOܺk#t Pÿvbp3á~j٘ 3ORĺS"HYٯo[!Gy5b4[|w#0[Rh{1El/Q>6G}` wv#(7on'h|0VKB2zu+|@pb$]JMSGRF=2m~yZWz8:Dhoc_f_!Z#߶kv=w|tO/-H|tAЅox~26\*/A'm8⭚'SƂQKyFNJo$qhU ~s&'ay{]$z\bA)$P"[#Ifa"ܲ7!)Vq,ot b@QdMاw& rKst¶3K.et6!T٬3ALP 1. ke@Af=eڠ\,^- ?R 6I~+uGslLy㞞ޏnp{ endstream endobj 332 0 obj << /Filter /FlateDecode /Length 12182 /Length1 24848 >> stream ֫}$5po!I)=%ϊA}5t⒌44Ln}h?> tHw4CQ7 ^4ӄ,їӝV!imK N{@-0[} ^~|xTע苶bc'uFʼ_$Yv T͔8F66RG&6x999Z|];Gmaӧ;S,/}0>|;G)',BUMj73QP^P{$ӦLRk.Cj6 Kx!%$(9/nm9{W(0)=gw]mڷ!D) ezpgU~Qv}F*j3f&bP9 V #V۪k:% Mw& .#RiL%>j[(vu䟶Pb>zTeBť.^q Tƚǟέf Ch>Im%=mz?hd@d(r"bj3-,dbh&B: ƶe1#9hӟAǥ|ĭEƴqk|D˼S"rGl_F7c,1|bpNt)4Tx {ʳD^|ҴPV*bOsdXYƉp XЙ7c#q5ՙr,Ppn:@BQ2L`GO}]R.2P"d]jtX6/tjUA cnQ}@Q_t2,e'uљ"eۢ_䏱ғT0[͒lOz~X^ɮh1kRs;l8آ-Ft}ZUUV*F8oԗ2Xu=A4{,`c?g_WYEL 98G佅fbaukTUaeM+3+޾ YW~Akkp= 8cp(bX.Hiv_ye7 һkv|1B.„c)ߊ]#'.y厰'yBA߿xsW\Bw[[ ׀!J;@ۨj;[ːxϠX@ Tse\,,V{FИA0Dcc3~UʗG_DoaAVrdc`@,&;\ }|_IfzYw7 ڗ`$@ 7t.xL6~TZtrtUX"A 8ߥvW9زufn=s1+-pV_lJײ3+]ddqdKhaZŏٗzS<ք]nweֺd'A"Zƈ|]0Iw . t.uq% m_}8s{Yߓυ+dkT<5k(Ab>_)t&6!^3A1ys/ t"[pYKB&x4zXc4+lFZfI#";7~.4CjwF{|zS jmɲ47zG gTe71KܵWu;܋!}}ډB!8ULӷa-׭ґ/}齂= }&# A͗`}*)cO9 %}#dF]Z + [@#1z!l6:F-DcL }wDgSf[}@FYՔ,nYvp[9h2蹘GD2%M aXT[dŒּ)^9FUz/V !4|~j)jjc Kٜ͠|;pܾ>v͗jsCys9uN!9N[+8^ĮVV`DmDnq3? 퉛3uBpOQS~;#QU5|BJ7@OIKF"`|~>^\B-З[6#St_'tنz枿 D瓈9_)x^~?α]wc.Y&KRlRJX49%!ޜB1 ؝>60(ZR$N3F$[U|rr YY6hsxt]$&^n9,%S^1  Ce\_YūkkBDcje/oW սو{2/蛪g:~[T3} KpFCͿ]aAu@3G6ԲoցKǙ;{ۜG%ۏkl;"}...vx>M2G&WKjjoJA',nOW)Q@t>yŋd7Iu'ap}nM 9Ma$j)&0haShEE[gB` d߹N4cog ~Sf 4ŨSIKUHLxGE5&IFmmX]ihXۍ3<jr]=W5]4S?/JXmYQ[f;i+kOuZh-E eW_2`-r2+dCQais- [iԝ+*T1r.l%7WE* \Sa0e*,ob|)Ev#ۊ '=ģD0gO4X/NI)#pV Z(Nގb]twS||)V\fI-[G%۞m鈂ɶf]"aBfRBq5E 5Q_V,Р* U+d<f'rˈS4XP >FnGuQ.O?輝ow6X-(RbM(bP`DŞh;Vp߄Rّ=7PrVjlٍ[@H/ry*`k$G@ qKE.Z>wg on+_Z{u@ǻE~rtR ZT1ʷmʹgOoYap+1 yW0"ޡ_A&{$'w1OE̽{@xhEF)9{K=Nk@{#\Ċ}-'!p]0QsUEs!6[VoXuPfv>ؖ>#}7-q7+}*Ǟ/‹[<3/F2v Dh]9?J+ G}3\i V(BSvґz:g7(0w.hi%T>R'Wty]j5UZ7VcrXA ES*tt<)؋GTu>miգr; >MZ5_r?UJaO P9n0 CioZ3KYa*+[ @Wre!F0$j/me<-@ Ŀ3yڤ e)dެ;_-ߕΪ1'FA$DN͐5B*Jpw8"CkGB @Brd9(UZ(b/,sc툆Aw998 *O0 A5/MXx7B|#Cٔ(GJ&}C Zt ΢R&)9IhT&Eq@71k49BzJR5~aO5Z?$Ѭ6d~8m~|w?IE~Q"2[#NO^:JMo[3T2ƑѱAҵ̏Y=fxV#iHsOS`8xP#.'OH!&H #S0mH_򮥋*O;PS:uIV(TiOYpZٕS\ݏR3E>% UDHԜH=kn)$Vz1`2XiY>Q s#~iM4̤ }/ a6A+4:lw= xƴd7>ywIIcWdRg]朳` hz\VhkBP\4NfLRYWQf(Ӫ>֡;ylٳGI?C55n<F,3s@BF+OA5_t_s>z /7(*f%Oi V \)%nSDźL sNzv0Vt'[TD ?!i8r)8 Ӫ/8Md,.+ 8:cS@XBa9sq ; inLD*un/8a;I@ ıRS#ʘr@*[` OgI}1W5U ~fLV(>;{=dH'҇0l'+XpM@5+``hS({Wta<\:S!ٰRLea8z/Snk }&IAɻz`ⶦs7ëaDz2<3{Yw#*ᗀm8DKj%df>"2D;<[LOua;Ą8ݑ傾Oc@XGrQNx3BjY`淮R4؀+Lj;SJx଱/QO6N ,HQ3Cl}uN5$-J0*&$~l60qS݌Eh'F3e\GZdGve$smxwJ#DV.y9Tw_)3Q&ÅuN-u[璻X}z+xhmkMA9o+JXe3d=E݁OdMpzՀf!GAR˺3aeBk"Ҹ6zuM+m!B3eFAN|V6:*X'\N_6%3V\睒+Bl[(ؽÓiWglz2a`1eS:׆3ro~*ζh96m5yH{ NBdz<+QNe6Yn)V' QPփa֍Sɫ M6ʍtTȁwڻϜ&iؙrJ['$渨J9 lzDYT^,e O^X4ӥ)7s8Pҹcǻ`LI˃c(Iɭr'P^=,03#..YlܵH)W2I݆=?sqOIĥZafچ\i/$ b{(;w ZDN+M:6G|EĪzUp[{p᭎7[iB8n'ip"[Efe̳lR"KH5 L%EoZlHW{LBNOƕ6?G7)`A/=I`3eKN]5 9 7`lbH6.=+a{ΆK%7NS1d^)$\1W+4Ez/"2w2e\zDſiկ$M[J+}A>,U]DO@{܆gB^,+'e!Tx3?50:Ziԋrjv1U~Y]8̯|+)(/BZt=m+WQl$na#/\m@w:ԢNxY@\W0XjnuХ_ 2 \C|ie@$ GPgXL5p'c;|3ĸo|\1=ves>Z"h 6ߛD470O;%.qA$m'B@?$),$A $Ա\ Dq CTE迓-m}8KƧ6owApޥIZGn2"Xoy:;#AFhL*a4/D >OJtFhh>_q3otq$޴I㲨2zP?xh)44*8ȕLFbaA+i@9>+4H[ra7w'V $|+U)03'8]q,G}n ]%TmIO9"lIM2縺WfGc+QvE^\2DB%̿ >N[}aҋ72_FR} \@,+bA&Z^'-^ fx)HmXeG,Z,l%kD;S;@G;qrG/M;S(ThT(NhJ "p3JHݻ -a_dR-Dp~ra7*Ѝ=9X/Gr&d{S OKk( K{ %՘|6:qMQ*.;$df2PW *Eǀv>-B5=#FJoFwM'`4~THrs&(náރ_*aCǻJ|F<5,rD$cxzkVϽoK^iZLoi41L!R/aboukv'RrJFOj?]NMioûIo1:p6=Bhg~jpjړg;yƽ4 5"X; 1*e1yA~1A8},OAB@ύV(?&`qk쏱iٓ飻@G0J~kP+II0 zdf8.f VlFϢS٦P)Q -""0FV;=veln9*.oŀ Rn҈:QdISzaB3+TvrdqOt= ]3*j]{̴ǨZ 8Gt3@3z4{h; ޴Α:wVjRD]bxZ 86:+ܮAH/ޔkvbՊ$݇ 8+ɹyп_{mLrCT&G,Ci:ٙR62BsOU&Q7G8'?Qlda *(%E ˋ{Eki撋Ӳc _ǎqtE n,di2Z@ q$I5~S(Xe.:rgWB'~]}TTj®02lDfF_].ܩJ4¦DI=Xӧ" }*ޏ<-adK^ǡj!Мp6zЉjw\@մ/I23FrḾъ! 8BC%:βD!U/@֕V#a8ߡ8<#kNz ^d $M0_ׁkFT }KJ5XgK+?$joMK+p9PPKE ԃ cGpGf "vڂSK.N%U+n76Gi<8Y%!t{z~XKU[g˻rψ]H#S[R<~{:8E9Q9"@^D1ۑîΚ_eKH:S0ΖÂ佲T[YB)Љf\DP}Lt"ޒEF._iHYFrN\Hr"5#rL rBj3]^Y7+ؚo OI=a2'O.34i5 7l?RQ{O ;wB6Fv#0 Q87ZbURBm;ԯGt[o;1|Ѝh);ZRxDUn=j鹯~=t]ւklCJ)_Fu8ෝp7a? ET"P#q=Qtn ܪ!(k5J,e6@jCvX do^%xho9d JZ<_k9anufި۶(C|L(b> H'Z)dži:/R% endstream endobj 333 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 99 /BitsPerComponent 8 /ColorSpace 305 0 R /Length 2493 /Filter /FlateDecode >> stream `H8$ MIkN}0%wB],ߊ+i?j:|8݋g&!ۓ6YX~"JT놾q?$Q8lDۂXmi˖êc?3DR SǪpzM!;-HpK(8x4% 355O"/ 5 Q]. 5YRGeMM&9_t ٖ3љ G|2#V] h#ά-x'LF:D +:UaM' ڳqI7w=QS uwQuҕ@H[O!$u[9)?+cBU !T1y>yzf>>_^u~rMCfr4hs5MWL0CB3ɉCA`[$!&N?u!_4| /u4|'閒 h-ε%u[ NϣؐAnfQ9O?[/W—|kت/VNVif~QHڝwcv^Й!M7"0$=p Om=fLs7Y׉?t|Ck]3Sp#I_FNZ5WrwM4]Be}FvX;:O ?*R ۓdp1]{F[]9`YRNн9.y 0Hzjd}?O=;_yPڄ`\&qgyU}QpĻjd.p0jpjo]bY|Q8DE˩b[x FUa7 ~|O<}|ł Ne6}5rG+%BKP:Nc0(11~[P5:f+0k wGi@ئ %uW#V՛(S+w.8X,dœг/B`0wlR6uLJsno8-'FB+r~!nzmUAlWN|s2ik/XA "Ѹ+L´fA-X(?JƤކ*n7m Hm]L&U7M΃w hrO-? 6 K s}a|Ͻյ{5 P7f~R $^e):ا.):b@ endstream endobj 334 0 obj << /Type /XObject /Subtype /Image /Width 167 /Height 46 /BitsPerComponent 8 /ColorSpace 314 0 R /Length 1331 /Filter /FlateDecode >> stream /)+6ϻ$ Ǚ{5~&9]y)x~6em^8ώ.a(0Kz_4GNqZŒLOo@/Iw;Cos*}U >*ȗuY5 ?V[(4{^2lmGG,cmtntN B$r!n=g3REUwA\u%$xQMNRHXǯ5+dm VhoRl~pSZE#['Ise#_}TIxeYo)‚xQ";78W _z8hGָ1ŎItևe%Fqޮ#Ψigޮ_F]jb6!dY`Zov#FdE-W쨆rܔװT4-D*y!+lc ;ܿs|u.rH.]D>ŏCcЇ!։XJ`ZK3݅BU}.o\2D _02R53!# KÙ s+FLnXw>Rr6 MaaYm/[/`m4I%vˍZz{z$7dR@j>8\xt%[#N_6 ׼-=X= $H@WCΰ&;1{h9 HV"@fTpX{ޡ}N/{_ ʦPW(ʭ %f ѳ@$.]^!qu̫?.iLEӵ~BTSgKIl$.MXRr!́ <+WEJ)Ev L8MI> stream n;EܚZ1n!1AwVEZ`&7$"3>K=Aݠ‡\_J_Cd薹}{jw~1?7FwoT5Ԑ5TlM,P vשP^ɫ$HE:Y͋6cElWTh N7@p?Lny*qtzzB59*3ɓS#+ug2=5p@p?%R;u0oFf|(t.>r&`&h0" CNkYU=`ߤSs7cn9%7 `Oc [v)CsUҤl$kfppY֋yN& N&@UdtAf@ʅԃwĠёkhN{( 'Lmۋ_dRܹ٬cbvv\Q\gcэ]=vO0#ЮUd`d梅^>ؓ)Ml%"-!MKT 1?x)b&zV,"]m1a_&հ7maXx)%/' g_\0(63M_[lɁC1 _}I ҍv9Y=7GgLvc&;^~hkO"{/lYfVMSj59 є᧌LOVmAbw~hYq%xVr/;"i)\vdt" 8jzY'7yD&Ԭ6RgkH3 aۉ 0 %_=a}FfH܈0&RӛJlT5y 0H9Ur@r[]qvOSTf3gLpmM.(tet?#/CCU@^B\_`D&U8kY$Pͳ S LIyF§ǩX/Yk*e9Tria]=HE hBY>Z07)̥pj.+Z HڦDYK9`KM&2Ѧ9kQ*'2bA!sh kq+4#rbG >e6A[&@D늢XYP4 D:@rIy[{(f1*+CQ q1Z?dV=or]M[rw7ќ7:0,o[,v4TFI/͔~x3-Aa{ A V# wIE70so@;xmM}8{F=ô.Z2PK0m$ij'5,Ej9- S|YvqHJÇUTb%>ΠnJhMyݺNh|;UT=ԲEX$ ')%, z ,lU|e`&"$gnU\r +K9$\yytjXy?@gGӐ NuR<3+VhW6):OE0-o{)RzUhJnHWNt/Hm*PbZ/3qg.sZՉ2Y $ȭNa+}YfUѫr!5הּץ|9Ao}R.fD8rSin鶓y#;Hj|iB+P(o[e:pX.r12ÀAMQP+g/jo"ѿh&̩C읕l|y]Lyd> endobj 2 0 obj << /ProcSet [ /PDF /Text ] /Font << /TT4 309 0 R /TT6 307 0 R /TT8 316 0 R /TT10 319 0 R >> /ExtGState << /GS1 327 0 R >> /ColorSpace << /Cs6 306 0 R >> >> endobj 3 0 obj << /Length 1827 /Filter /FlateDecode >> stream -4S6wVVj;Fkzv66<)`E3 m]M&#V9G972E FXvϴ:ȒzW+Kp1z,жY%cݔ |*BBɺ>R_^+Ӑbi<JʈWBh"=Gs λ)JN2^x A~DXW"WҞ[=ǹ "ܙK!M _d U|TQh#?f:Bn$jhh58ᕖ);`K^YO2g-N2'`}U؆(z37Qfj)M\_W[fW" w ^i>v-<0K_RJ.Pe_>Zw\ظaȹx1dJX*d(u9m" ,R[pΞ #;ve\88ꡭ~iֈ/K@4קP۠ԃ,O,"L R{.f FZTOՓ)(v3YrjmV4H᝴0M6FB.a=&t':~7 3;.Q2:'m&X'm7#N[L_7ڻpQ\aL\ E-f#^q1T:*A)ЃAeWZ& |&KQҐ)Q#BS3a,0x)~7왃Ѓ`YSq^NZX0OL.ߡ Hs|7Vdlz+ަ@o M i+w:gyltO=.vOԟQӅqV ?15ˎ}I_ Hcۊ! mNR0ܚv=šF|T [gL&7";5L/HLçҒj\_èi>,WS iiXkӮYNpݗ`gFQ=,mP73CӖEgx[f!~W`\*3(Bb4WBKu^Q2NUA$'Aa~.'6j̕F n^^ag5-"5 PDm?WDWv;s̔6(e=I4`O9SEH Pb[xo$kR*_=Am M"7V8[HF X3F8 UM'Y=^<6ֶEu:T<{D%6gt~p l[̺c&]- endstream endobj 4 0 obj << /Type /Page /Parent 296 0 R /Resources 5 0 R /Contents 6 0 R /StructParents 3 /MediaBox [ 0 0 595 842 ] /CropBox [ 0 0 595 842 ] /Rotate 0 >> endobj 5 0 obj << /ProcSet [ /PDF /Text ] /Font << /TT4 309 0 R /TT6 307 0 R /TT10 319 0 R /TT12 320 0 R /TT14 19 0 R >> /ExtGState << /GS1 327 0 R >> /ColorSpace << /Cs6 306 0 R >> >> endobj 6 0 obj << /Length 3669 /Filter /FlateDecode >> stream qt3 p^HUbl2maIoIsۏbk^`_$CDhCϙgܯ `Z"+[IpR9fY֖!au5dF NfzKUdړ@ I8 O*f&H@_>5(4\W"L/dVa5s U 8T5a鹝*~ gQnLŵkbH9Ƞ5t2y?h#sfhxI;ܤߐU ;q'Ma#|c+=jiVNlBV݌.ƿ-91% N4lDbhF3'1|z)BHKh=A}KwSPQwC檵]ٯTnSA)-ӗG`$3FObWW ETYPLt"s#sjR"04f1GSZۂT8+ (Un!mɁ $cQ槣bz:/B+k3n(ȥy[R}Ckٛ]V0Q\+NY^9 Y}p05X\11gr`V$Mʧ~p$ܑ Wp&gGb^*<|XfL)hG!4LcM:g )r3zrRP=M:[[~6Iպiz9oħyv8BKquhY9Ye|G U}F9cA:q\~1} qGkkfqm{2&%R!j`ή7}ANduw8| =sμ~ "GHbhTe9Ng7n;z>zD5BUem> =m l&90@(gHkrRk'P;bsӎ %фt+r5}D -Wg? [ +w ޝ&a+"Ra]< 0m+w(84S'<1 crlkV).5pvi !D-@66 kVѳ8vjfXP6>HJV6vNEsXER& +6)CD-9e#悿M(ɇ?%S-tPA ,aO:Nbb89\$&NԚj_AԀKBU g3W׍ȰdAMCBY|.BRє#?tX]t9~¼?3\5dD"bQ@#tV1䅛8^.vBR q֦YZ^A *-;6‡_ua,4lFư ,BA0+)֯:9[^KEh݁c-IF^:?t+WEMudNJ^J{q;Ka:qp.U>VZgB%8yg9lC+?<~/)LJBf aF ssha_7"@JՍ(z T+]*_$E˂ [zY\(E둡Q~4|ho 2tE !Md_7Sp8}/NZ'8Tv)RO*Kz(?bd ęjN@`NjSNkfU>&/ RāB~>&6ɹ29|/;u0)ғMz9B]FYRCi3{b/erE]y0ssqF2 !)}s1.#F(~&j[r9,|N5?h sXd' LVBMe:4#r~71B7rD3; Rlj=~׼WHyۈ6pxTEpy62\ endstream endobj 7 0 obj << /Type /Page /Parent 296 0 R /Resources 8 0 R /Contents 9 0 R /StructParents 4 /MediaBox [ 0 0 595 842 ] /CropBox [ 0 0 595 842 ] /Rotate 0 >> endobj 8 0 obj << /ProcSet [ /PDF /Text ] /Font << /TT4 309 0 R /TT6 307 0 R /TT10 319 0 R /TT12 320 0 R /TT15 20 0 R /TT17 21 0 R >> /ExtGState << /GS1 327 0 R >> /ColorSpace << /Cs6 306 0 R >> >> endobj 9 0 obj << /Length 3336 /Filter /FlateDecode >> stream ? KTK 0JVoG]TOBrj*ѐx(C~LЇ N3}v~"Q'lXEEN*WÌCYy+vճHL&p! o=(Z0!o6y~C&iY7r5Lo مsKT`\p>Yϳ#y=FD*'pK Lى;);37I_YmoN:H%9y2"61=D/xf~;@<& `D.Qȝ.L;'a?I^%\t*6GVh`Igr Z5D6ԋTW޶[)x8/& ɈcnWVfj*? .*^qv21\c<"mz}^NWOQQ)Rg`bN83H(up i)K5XFX:7)z DN15ᇽxݜ+Cu_m=W `s`sδ,(} "OK> `bS>#U{ Lp廟=#C G/H<Ѕ;f8BN^OWX\_ZɭnJ<%"drpK=sȘm[kC?_e&vLş+ +L##D].`+ s\/?`,1}u%Z2XZ #"Pjk8Ϝ&7RDYf XOҵʳn^ e-ab<O NʟoU5!O_l}wȒ sT"R[l +.1(G[ \J^[cNAz._ 'C9ϵ.an >`Iu6۲f,xo71=3s&4lF  g UVG{^B)s20#c+*% |B)LkM*y轸w7כ:[ԓԭ}g)Ջ{L FmE@?],.;ﰶ6Ⱥo n;\N&4zbV !m(v&yÒ&O;Kt<~9 D]"X8QwИ*U쉬[oc) I_}4INuUKf>DP״"߫9& v(5bCU( G'b#B19(!?uVZk6wlo)O2gC+,ϛP wB=Ï]-xQ<ߏUEgn߈jK:'ߗ4wm_cf[^քOXj$S#V xK[dWfJ,n.A)Y*p8[j ^ !e7nsN^ .=Afɮ#`waۤ$92!Zd=16ۻ%r/#3fDHOSTdO<77)ԣo ROf:`XH.6Ӓ6> endobj 11 0 obj << /ProcSet [ /PDF /Text ] /Font << /TT4 309 0 R /TT6 307 0 R /TT10 319 0 R /TT12 320 0 R /TT14 19 0 R /TT15 20 0 R /TT17 21 0 R /TT19 22 0 R >> /ExtGState << /GS1 327 0 R >> /ColorSpace << /Cs6 306 0 R >> >> endobj 12 0 obj << /Length 3522 /Filter /FlateDecode >> stream ED} F0 OBn !%A{_Jbgq`Ct*Vͺ饍y0T*g{dDxJ#xaxlvI*<'Ba`سB2)óM :+ 5tSiD\t4v#mKΙSX@@ B= g}+ ]]yySiFg Lx=Lc^5dnXGW1e(=Si<1A&F>Ӈ9'"3kej2Ε,` Sۜ\B);3\]Ou0b\#eE9Y+)lb;=>z@ sJik~C{E|ܱT-aPm1gԿIvgH^+1GJ}הR s<7-:vu˩sr:.[ܕ$M@Sb(Zv;Q ktOF+ߖd!2[ꈏ4ݓ"ٮ"򩹣\t4;J%H' aB,‰bQ15rG6wḧyZ6Zi(?hVPnsYpE1$΀e,w{D.8D/ϵ̤ Ѯ)jen0svا&\ V;@\p+KS[cCys[q#IV74@wG&S ˎ Ŀ,ONh GN3*mưj-wx,Y0O9p{#&Bz833G|e[B*SC=:&CvY;= QąKTP3دKVW;z~C\N^ˀVE%T p@S^FC&M%gSyɚCER{$U[G5wPM! n /!!fK`1S)^XcyZCa=YS{4ʽ5clS{$  D橀y$)ێ5Jzza-a{T$ߴEPLᤉׂ1i>Dl]hDVtMs٫ ~z 8.#|b* m¼=87xf:n/WQkZ֯0ޖtM8D_֋7Ii@[ W˃M\kwSIV^HI'Qe N۩imyO M; GJl> 9]w& 2SQK\1JL⋧A][ޯ>S)0 ,J Ag3n1BԚx9m1jS#R섣vӗnYPSUM'GOm]c"a*1o蘜b=MK^9xFJ|\0nP,Ч|6n ]yXpg-۫ﴖ~YQ5q/7R[fҮ XiV9o@xp V,n~GS_U 8R-%P?[@8=wm Z<9vjD_qLNI!ysd(/r^,3:!KȺZE,Y3xgaxXk p^-8׭$RRJm(SP|cLqU+6Dllq+bwuzH.yIN"R-@$2³ X@NjԾLA|im~X=y<\C !7?dt|0G[Md|NBA+EऌWY!1\'=~v[uټS}jpXdDwS$z]D48wm*e47=£՗%6VhRJ:g(=Ł'6C;7\ ^LNܨxrՆ_! ΌjE ;uK ,P0{bsT0*Gc_fR9*bZ\폨^EyE@#bvc,ndދ>ސڡ!\EY?L-MDya(ͽSf GQD &`nhAxWdi^P㨿֯xYODĢ; Jemj&@DJ Ox8Cx!EHlQeXJTDLk]ΨI SdD˔BE\Fα ڀ[\қذa:-'yL߹~T^:+$4{y柼W1ccV6㑕$xP[`Y%/YGrOj7! Č+b6ӭXC endstream endobj 13 0 obj << /Type /Page /Parent 296 0 R /Resources 14 0 R /Contents 15 0 R /StructParents 6 /MediaBox [ 0 0 595 842 ] /CropBox [ 0 0 595 842 ] /Rotate 0 >> endobj 14 0 obj << /ProcSet [ /PDF /Text ] /Font << /TT4 309 0 R /TT6 307 0 R /TT10 319 0 R /TT12 320 0 R /TT14 19 0 R /TT19 22 0 R /TT21 23 0 R >> /ExtGState << /GS1 327 0 R >> /ColorSpace << /Cs6 306 0 R >> >> endobj 15 0 obj << /Length 4106 /Filter /FlateDecode >> stream Je2?tВC?GP=L XbB^3FWA՝?|ᕦI$fع^% A).w8O܄be|V#H'Iteq-M ] kIjQS|&mRL`.U[/GSA/wkm8ΒtTDچg{@-PjGgAȗj4}Q %r`FS[όB%G X $cQ٭,%F4!*Jy0wubO`{#^~۴*YBܯ YSuٸ) +;ZeC-QU^ueAV~J)J ?[ʆ9kAHT&©oX\J7͟ #ۄHx H5 b?9$~ )lc= 2&(9(ś0Cű)F!\.;o|mGn h%޸5\{3YP?AڒxB !g\ރP79+7'gZ;cɥ,l#)&AƇP!>`K܂`yG%&x[+3f*%~0lO ristDt%ȱd̆:]:!]_\Jܨ?GAws\)f'+vCD*`#'Zs_B^Zdq0 ZD'#T@?HIGksbYoL&?C@  KfO;P͑_k691 S8h$&\%Oj qFj"T ;Ga +W@&o fnjI]BZGar(  X4;zлxqB?fguaИ g+11Uoc:.UʬdZR}ɿYrKf*YK0⊊1ú ,C; 2e?>8 ?huCId_Oq*EU)6CTb-ڻ1  !#yѝգ CATvX8K%pbD^^.=0 E~|c% IЛ\ |R'ribɯ1A8w@%ײzg ` w_w LOv>ley,UQfh0Խ6Қ'(b ޽ 0Fۍ%LFL," e/8j9LQ: 2lU ]N!ƽJp*i2t ohۼR%R*fNҏ (3=Js8zzʕh|a뤾ܩ1>w4`N-jXv۪YFnOGi7#1SGYkTM!ʩ DT8XTeL&F\Lb_ ż~I&L@YXii ֯1"Nx9C:_!Z+"q/4;J'^ Ͱi%$2(}pp ̷3_ˢ*WG s$ܨiH:hPhsz,c4X᚛+8fUZ=25 ԷlD6*Uf`P6paIC[l#8@~g 7׃h>7FKs6Yer-{kY;uBYbMۘhȻ-y1F?؏K|jc,l܍#g&%/OfA1ib2;['`-̷tnxk_a/2ZF.-7 6ʬ2qe"%3 -H-Q8Eapvv`6HWe |tR.pq:rB%O>1Ow8 kbv"*Xp꽖%(:px};̚TQ^` (9N"T"Op)rsVi0hll;+ q)g2lV&TKp) RI֩WnQ veR=A,)i;.7 GJžgM,Fi+Ů~ 8z|S6i$h4a<' @ѢY[`bp\1Tʇ0ۺ|sjR~bpz#6eX&@IFnrxF5~7vSsg6f?t>Dddvi vgHeNlr|MAYs7 ? *{^t lvaʱ㚍1 b2vك6s}mR;<*,uDžZYlQ@ե_ #*1[I6Kޗ.,3CkM*HR [`U/D_KJ*UKMȾY f#eqBPA<1pYb{OZ=Fo5.#7Ry]˕!ނTP}X e+́ג!j|JxQDQxq"AZjӂnc9©&h%!Av-<;-+H4)G5F\8s^,UeP q,F-ԯſCPjqJB0Io5w"Xn>RW{ бl&؉P'73S ߥNvxPrQ|H $ZYm,EvXv1K6CIʧknf~#+o,OF 4[`3 ϶d.sLkVrBDBOr3HTfO5* ]}>77I:0ku-B1޲{w&e|?_Lv#b|u"R]'ye\]N5do#`=Oh)Xc @6S98H-hE c6\O"cƵU^ endstream endobj 16 0 obj << /Type /Page /Parent 296 0 R /Resources 17 0 R /Contents 18 0 R /StructParents 7 /MediaBox [ 0 0 595 842 ] /CropBox [ 0 0 595 842 ] /Rotate 0 >> endobj 17 0 obj << /ProcSet [ /PDF /Text ] /Font << /TT4 309 0 R /TT6 307 0 R /TT10 319 0 R /TT12 320 0 R >> /ExtGState << /GS1 327 0 R >> /ColorSpace << /Cs6 306 0 R >> >> endobj 18 0 obj << /Length 2285 /Filter /FlateDecode >> stream HI +u'$cgx.Ǫ g} H/z|ܞy̙6 NL2jZ4fꆑfBlJrSk :/-!ރs'x'ĜW!#$ eZduWnͷY7 < R+ߒ r~ҳ+m 0iΛkM/ SJejlg'CaNXTM/%J3(yJ)Տإt7D@lѓ/:[rolt&TJaN $-*MQ`/NzTP$y~;ͣ X(0[ɐ>} 4?yߡT3Jvv|uj1) M]N+9 L![^|QhbSo8BJU3 Ey?RHZczS0sRsٜ_jhlkbC\خ3TTCf衸v:ɢ۟\%cϮ7$$EBOQa*om9⤁!ОYY![0lTz˧ޘ{^8s$'s;A\4cEߋ@*_Xҵǎ,+vymt ;R~!cO'l,$_-vS!*x`)k>JqSIN)`#`{3w OMϥdڂܛqXI{D3ij#Yb)aS6[K@s <(y,(g-GS}8]* #\W,3{8Jq<,5A77ȉ4lx7olJU.!@0UMWHݧ=bcYvV[\w򠥯MW|;+a74 P}&Map쾄6m$95W7o@gl(u`SCv%6`p )+ bt,$\~ujĻXā/*Wm|R\cjeϴ`b( sCw$*~K7eܝU2zrN^9Ȉ.e|播t}eJG ٜ,K.. :\=L*TΏ%=3:ݮcsyjmV] hqlqJYO>t%s Le<d!6YA|W/:tC!0:i?ӊ,Oc9Z6P`U#2oBE:Q \Sն~R'6>&iA0!LO4AbX8L~-06)FBu^!QGenG>ďx t]$ČAp?ia=(_w`j*8?v8WTrK0JwH}Lz2b623[廘m,Ve}dҲa@v{.lPמ[ih{Íoy*|Ѹ' f%Y1 }=^T-(W˜}}Hg-Q VcO"\q*OlbbfL3L;!lOڣ({l+S ׾OCd]?K.nlr,kG Ng /~rh us6 瑅>kNm<5_)EcaU J pQssKFhd Npo%[B\r- ;+Rfp==,q$:g!H4w LK}' ;F=#0Ge uy_T|@wp 7iC٭}>]La;4 ;A؆abx%oTa\2Nɍ nx@C`WL/X\5Q=UHՋ.4|u;W@ZX3K?my^̔^$0q ?{=j`MgXUJBpeqT >weD֡%&ςfmtO͊{yQC endstream endobj 19 0 obj << /Type /Font /Subtype /TrueType /FirstChar 32 /LastChar 32 /Widths [ 228 ] /Encoding /WinAnsiEncoding /BaseFont /GBELKI+ArialNarrow-BoldItalic /FontDescriptor 24 0 R >> endobj 20 0 obj << /Type /Font /Subtype /Type0 /BaseFont /GBEMBG+SymbolMT /Encoding /Identity-H /DescendantFonts [ 34 0 R ] /ToUnicode 35 0 R >> endobj 21 0 obj << /Type /Font /Subtype /TrueType /FirstChar 32 /LastChar 32 /Widths [ 278 ] /Encoding /WinAnsiEncoding /BaseFont /GBEMEH+Arial /FontDescriptor 28 0 R >> endobj 22 0 obj << /Type /Font /Subtype /TrueType /FirstChar 32 /LastChar 32 /Widths [ 228 ] /Encoding /WinAnsiEncoding /BaseFont /GBEMOG+ArialNarrow-Italic /FontDescriptor 30 0 R >> endobj 23 0 obj << /Type /Font /Subtype /TrueType /FirstChar 32 /LastChar 32 /Widths [ 250 ] /Encoding /WinAnsiEncoding /BaseFont /GBENEF+TimesNewRoman,BoldItalic /FontDescriptor 32 0 R >> endobj 24 0 obj << /Type /FontDescriptor /Ascent 935 /CapHeight 0 /Descent -211 /Flags 96 /FontBBox [ -204 -307 1000 1107 ] /FontName /GBELKI+ArialNarrow-BoldItalic /ItalicAngle -15 /StemV 133 /FontFile2 25 0 R >> endobj 25 0 obj << /Filter /FlateDecode /Length 5401 /Length1 9980 >> stream Q.܉uHQ:OuSxe'؎:bOa¢s֊4ZL&ͤ2wR{=O7Z :"e! 4$3$Kd찑(6o$M_Ozg20E2@%@_x/tWo#{k^hdSNžSL]cnPZw,M'~Xq҆9WrӮgI'M c b!ـPm0,X $9IC*NBR~L̴Xc32_n /:<|#Zh8f ٫#lɧ:JcLo΍&#7@:8: xʵb .*dnT x68㑋$YbQ8ꖟ^'5 w$~^J_~oR3) )&'& Bvp.0W_o~Cb8UYoЛ9g ;O+/^Ps$ BOT j@g?"L sʜ}% e K,3OE_x_!QrP[i]1ۡʏP\k)Gw3Ni2ǭ|GL`:ۯM>Oz] j=&"E~WĮH$Sq ›kKp'*>VbyD= S|Oq_y!Oln&T&C1 v|wǯ)d/RqJ/ Hh-Ipmfx+Vթ9x` p.^  k`ts ܪ!兆jVGшȸsY$;b\GqgаX2T; vl^ֺؒ.' 'i?( ɻJ\Mu[+H8?@*A%dȈ?S>#P\{[sН Ґl7HwIdJT?Xj1?3 ΐSm^aAerw\<5}8O3i RjkrajU' h3dҧhS=՜Rf磨+ًjj(O?3NaTO9#.]8_Y"]R hXIFn;MnDJ/P4ro]xz%ߘ?`|!cj3+_)NnWF+qU}y1):zlA7tڑI> raX +EXetE2"?bfH\\s1^VruS4-{g5 ڶ~K}:!jvaIIbFI^Z(KҊ_Ȝ}~{XlHɳ@?Z,h L~"[f#ܦ ܬ]κRrDsDl>. (DlrlgT[2TLQCe喸*Hjt8Iv2󘅢CEͫie/;I, J\"Y-!.Eoo\JFvdӀM13u;[@Se S@%AbdCɄ %tã7Xh4b4&E7GL?6>=z.˛]ʰ1'~Hk 9U!,a+/N%W"Zo8XhS{,b@S6xdzr ׄL/psRpi fHoRmj[-)//c?9hU8p=`,'/_dWdswv Odx9y|܊n80R fkMlBҝ#1@n {%4:⮎ ,b+Vv (+hGSz5: *l\-_5UCeIߺ~3IB,.܈* cixF%/ʿ~Gk\$|~Mv]U+ȌLN?Uo.&N& fY溰!6KǁrMټ~+dR>B:(k_6๤4k/W:0mCq?'[U~ jkPxEU"Q¿ө`'g (fݦxĦOYu"`#}@l8d[$plTR臯'ӜrJS΂2 S׷3V^۩ИZ&DiEEɷ!p+M9iݦT!NYi}IQwop8j~80Zk{x v΂ו_ }+$ӑނ<8huurMV5Hq)Qf)3tRy-0W" nT]-3BU+ ¡ufzM!H8;Hy"SE#ȞZ ޱ%)>VndZ;a@dX}Ya@`Pu $cQb|["F֦'.?>tu*!#M<ҝ #˺`c86oD}-s6jGI3+W숴 ÿ;?񠫪' * O俓OR'PMb" -P]OBTwzzUMkٮ@ }X(jTVhkT2>@|"&g>}A9t-rhȘ(OEXIm{9_lE[6m

m w3[-Poxf ǖ:Kloz\+igQq±bgCSSJP`ڶNg [.WhAW`bac_ dj?id+T0E7]\偂}6H O'LlM>̬{1W,uR]RI?]GmEuѴkl1mK;T*H Qj.k HCRɹj -1Yc6Ю+)i|X?k-}wOd 4Ox}[\Nɭ&i bW>hqD!p 8? I'D.5/?x+{檈^ufqF,oo Ăllw0Iu6wtqaQ^Ί9B܀Pb1Qtk5Ls٘~^ڳ( e &o{Ps(>œ{A4cK R:v %ԠW|?p^U2\X<^3ui %9ܞ}:< 3ə??`3ۉ_|iٚ/Ǎ.~ 9|5mآ<%S lw^VЎ7"ۈ*tn]T.y4Z(d䳫 XBLX3x9H[c-,F0 'uJO*!{sMyLDS#/Mo)hk`5s[bYd]uG⽤2hm}H+ I\Z8hX2 X )"ðU`*]kzRIW-뎄=oXFG4![G6loڢ#ZBaU?D 0%"Si*|U: XăMKBݦ]u̚^gܹ7v)Ӡk::'85N@bg!E)(|=^9mD7e);vgTUd!NS!\-jQy+Gyçf@vX뻂&Xa Pa:Z~Qxaq6vU!7 ʜ17&QDR|^YY ;hGb< L܍ 9o$4&[ӈ:UMv6@ !Bg_ Mzy ˮGL}=sp{Zu3=g酩8Qmdu=7'O\E>t.ZsVi23>Uo"Pڟ#TX)y|ſMsHу`oKTf(:Q;bj ֞\w{XdFgOEtvjaD@[hHDZɚRkq|.&-H}&:~ 1ճ0b{1lY X{k! Vq!a[8B쨍KRz_M$% 1A!cy/O dLOD1:dş y0$+r+{(1Rx6gϣ.@ާK3lz;0HFKZS eF%Swc(+@ [LZp,ezQOo& '@1+M=f&iSS- 0INXUHf9x9rz6-ߴ Sސkz{#B`,$LSA¹09yǭO5K4&̂r'J.hE9f,=۶ 涝,¾Y!E*!z[&LµbFSSs2~U6E^ endstream endobj 26 0 obj << /Type /FontDescriptor /Ascent 1005 /CapHeight 0 /Descent -219 /Flags 4 /FontBBox [ 0 -220 1113 1005 ] /FontName /GBEMBG+SymbolMT /ItalicAngle 0 /StemV 0 /FontFile2 27 0 R >> endobj 27 0 obj << /Filter /FlateDecode /Length 6571 /Length1 10232 >> stream q:=@lG*tՑxJ/h(iWCw-d: Jo{pJwm+DB,ȷ>:ӈ)?8AU^u!CY è*ze=tu &'1kx2X><>OTK(j)S俤tsTM$&ͺ_! 3E h$7aV{c?c)_N"Oȭ}8 7% =ZZ^5yd3;}UBʑWs x_ cܘ@2y/꬚R b_j.ޒ„)A 5 aW'-fidzBH6AaMgDZP !F玒z9ޕJ?Yh (fz>*I;]m=_Eu> 80"Z(4(H5sNmr dS=rV+#/CB-{<}f}ZLY#DMsخcv)SE*LRWhS'Tх3Ky#2+;v`{Rx#6+p*EqMtl]hА28=CjTX=H=1bZ0n`g0쬽ynru簎yL\m>q: ?Q_ǺC 4n or<g!XߴnYTR/`1ɥ<霰m9cv%A(xu0+Ww^X:h*瘇*5c7<z sAu77zBIٷe-8 D\yF0B|z)a+TnT[L_zE8邏K?/Z 4;}A\p`lTtnnަ 8th[ ~+CiZ+h|ieUt*:fPR6-˖&=z4~'Y;k ( 0YDx9gIH[n'+SvBD~'wH:70۩TSް;)D!iL踫.mea2=v[j O`-ɚ 딼O@N=Ax#6](8ܙ,^]Wy?@zn0לS4HwسV) "y^%Ej'lI|-Qpܴ_a#<a A镊ZbX7"%6YF/E0e]dH>ȹlP8aΔKpT1 H'Ϸ5sGi\ScA565Z]*.AbT^nɨ4T5ZJyeS'Zƥ?X>Q6h||03 \AaOor:9{l\ kz[9,2^nRh> Xa۹B.px_КfOZ̊'nJPw}{SEfD1&Y׽"#%F_\ρOnOr߅RNL)ڽձI?sO"UBդ8mߍ|l۪yG5މH`߆5#~Cj逻ȟ;7beld4|=Nӿ")T$gj"X腰f4u 2siONMT"y0"^EfAfo8{B-\-vꏣR%-y2nUg;'~k?ne=m}ު Lg_ tgP*~"A\;OZ!.3vVc .U-~ i[76"T}ѫV즓%w؊]Ģ8MSҩ5yU1yׁSJ]:T.[ ![5U(cmYWhxθ2ҕq ]).fI1 O0jV6lp?w-n(e{;E+e, nr;`!U~d5Jw1cC*!۞zn-1C=;<`كy5yy* 57RB2Td;O&D z8 |A71yFqb<6|OXm@/iOk_% _ݒJi E#""yZX8D%(g,8i@YoAf`YEYuuEd. 2_c9TF#"Ǜ^)*HV9|S:/%loKr0l@Md.M$Ros&]F>SG'@.tBj{80FɮKo: fZsubOڈjph |eܺVwG$G:qYzJ7D =4A;Fmޤ?RWq0˜ ܩZ\j&\YKXoq-Wi.h[.*;w3psExg;IyVs|`nx;b1ە2-5I@BJ]Qݔvq`/0v7Qs~דn.]t~B 8zaJ%W/ ie`!X3&!uv= x&G뵖$z+Xaͣv8}x/OYPӹ9Q!)͵lf~ !)K#Dܔw7ӷlPv.,roB}+Fe;f]qb"cf52BZ};13v9aIMLB51U^ ` ƂW00 |-2@oOЩS]kXv .)[][&b\$+[%4E;3&,#Aamvs;f{"j\AfYk {IBBAw&WR;箍}1|xCvp$IF0QM zn0ZSiqOaF6h"Pq_̺f,=ՀSNPꇐ*D3 6/?Bg ,NLU;m+uBb"?%qڋ ,_xvE)wz{*RB"wL[6VrIQA<mo)N3Ŏ&ܨ00We`Qbr3<{E6d`s)Asx#ӊA|jLc!0Ԓ૧yn--܀d>jB-_Ī zvD#VQPԕla"p+u4]$lÌ/q9"]xЩ"O?Sؒ~J;g71BcXqU{"[ՙqZ3Tݏ749W[T˹G HT8 yis뵟i+<dLm:Pb0<6Mv=$G9iTf2C[?ea(}*a-EX_4WC24(]OEd˳=z^Rv!58{ƞ{jN&MG>y@F6D mаoCM :uʊdfec+[c90hǹxm| yN.ITZ kg(;N@< 5I"9+82\{PwqvypE[D`D+ 5Ďs qEwBE4y Y:ړYvhf  ws)2B' %"$FkXġ$'uvSFrXZD_ᤧLKׁjK 9G^9Q l.eWZV ,{*A1dJ>u4w %9A0r>RgLT:Bxl鵙絣`מ:C<$ )@+xbgZbsTq[I qs )EDcB*C#|xh:U(p[~CFQM4RZZ FjwH(ZO.qLj*%vm 35gٍ%Y5d8q5MA cT^v {6jx @8HQm1Zx35K endstream endobj 28 0 obj << /Type /FontDescriptor /Ascent 905 /CapHeight 0 /Descent -211 /Flags 32 /FontBBox [ -665 -325 2028 1006 ] /FontName /GBEMEH+Arial /ItalicAngle 0 /StemV 0 /FontFile2 29 0 R >> endobj 29 0 obj << /Filter /FlateDecode /Length 6828 /Length1 17740 >> stream AՉ*L[bDJ]={B>tܞDm :U 0s@)A}ܚ "E!ז6AN]Rm+ܛx\KVR2Sn= z8>70sALg&䲄GP{8}=˄: `TNGqv2i[BzZyVTlmBe+4SGdr ajڻB^A {F|A~'SvS:":>}Af>f>> Bd% 8*$nwE:rЅ E/';FIm*xI@Rmuq){-۲lL=kVhm烅2p ntz},BҒ!(ЋPHZ]¬l| SE0o9kyE?r֭{:R_,8LڬߩuDI y3u#_r }?ʝr2~^pY᡿H6k.6XxВ_;9+y5GQyZO EdT2⊍'c::f'jf>U)*U_u\Bb(/'h6h3?[7^/ށި cC1 Xuc z+0ݚJ <*+[=NL$VF8sC*(U鉿9osEf =z{)@0iIV<[=r|冗2g&yzӛJ |+ŋuxe~Pl\,~:>0%leEhJy8EشF|.B˕v{0;שpe)ȳ75MV# ݾS4X~`j;=6"C 2i#/ (D,LG;_-WtA'@&c :ӲP>#]ZE.}*vY"ajjV-L֛wL\3gV ^y f|Oq]78bGkYl5H`wDrEBt=ߝrJIĚ)L[ i0Amp`hU $=*0f11.YImPL]G|M.n38jJϹoEetSx:0i\:#Vyv]^Oh鐊0ͩV5qVGWf0yNXқQR4љ{}[;dRf r_dk8* Ic 0[ק&X`KE]y1xUb6.Gf_*ߪeD&0b?]B0*Se*E*{a8<PPRYDSqS mi?Q0YCJS hp(8k -^XOUbXCRg{[X_9'z}X Nk8PKR 벧]YʐA`wJsә}\SH,P$E5 @1<4*b:I ^[c;{ _z+q{Ruv>Tc!J)lOm,<^i?EKyW%: ?-ق]J2mȳMrPX}PsjRe(3޸&cQ51SUPUKӡ֪cNN ,RA0xV.Uh X'-~]hd`;l]|!g4FC~9w|*>)ԍ>POZK >M\Jg[UURE8&#ȂZ5&Bتts-x(Q|ђ!$dIryYeBv)" pMQoģ zUQ-{NQfy~KN%bCꕄ/0ŠtR}ZpC a8FFN+9Ne,+iۡ +`⥥%܂xn1`$;p=#ݽ:uGAV4o˶[[&Ȭ[Ӈ;rH+!_ip;:\CFJ4 NADXXn3}crURYLf #Hh*)qϴÝ 6$=WMH1 0*Ħ3DznmsbDg ,e `w3L?7("@Jy\ @i-3uvo^ 5HGFIюu\nKV7t1nŪ<~5 ]Vb/t8!LGwL#bBظ B i)(+en}m((ȄEa\!B+S=ڞ6R?L~:+(d$I77b-5O;1Xq:l?Vp{QRuW>&R Ԏe 幟eS.Dˌc.?w˶8 ]g-#6η! b/vy.AMHac8pAO6b]ޔ߿r^14?lUuiT:RtEUY o_՘|]ZF{tPY9DzJgKAS>\)a-2$#cg_wq!:ǧsE#. (4wqݦO6٠$YI9Z f*'G9dq9`,4)A *vMo*ը0ϳ#]xdk $6\rfLjU ger/EYR8*gdBrH6A+zك> WH.DЇwp~#o+]s"*Se;Gۻ!fԝœ2st[P]d<%1QE.dyGu8{!D K6fdC}%3G9,B/F=87SXJ wNomaI?Z)h|A>l=)fX0q l:g) U܉A!\7iLZ\8S"!ّK@ 0ۍnETXak & ŸZb+p+d̊c3sY/Y $ =Y#mD*|' f: yB9Ҡ. !-0LշO,x%3L*„3 <2~WeH>ݮJP@7Ċ#$Ïx܂ _.#L Y'^`(em\E $)>ݙμr';4=(.6yW\4sF9ͬ 0eI8LTu*ș=^= cW𡚡r+WV¸Eiwy)֮ @[s=r44ȧG^?{VI@x8а2!]Y^ʝHt,KNhkWy 11-yd"vc^.xJH!Do}ė$r` vGKqIAXLCo&``VPxFL— ]ߚBhP.eĐ{7<$-!BB?cŠa,c#f {&l/gP00SD}6/Sҳ׃C5cB]K=_{`Z!#[ΩtPs_]n[~y*8FP'PJm(\KF5EX8 xeh=A$7uW }vsM!fc/ۇh^v4><_tNIH̰u4^8 r:^wkkjd!Jͫ%VJ.ļhƑ>V/RO 7/ě{ { lxS_kșR.N857w:{x;q8񑐔:AT65UL6 C }R\wA*LF& *V 0\1 |qKf#k=ڃdV w"8kV@yY1?8nR 8tJO:DEl18k UkLXg5'0%`>T ހz4 IXbY{**0\)LUu9#E ֨krc&71(pDdp7ɮ3V9jllh'Vl6mϰ-fZ?ە#`kvEG=H{AR7WlfFw7 ~q3%MJ[vIV}|L aJ\Eݏom:G K}ݐW IE8,e5)!3f_E5Ly8]hM#sj;Tr endstream endobj 30 0 obj << /Type /FontDescriptor /Ascent 935 /CapHeight 0 /Descent -211 /Flags 96 /FontBBox [ -214 -307 1000 1048 ] /FontName /GBEMOG+ArialNarrow-Italic /ItalicAngle -15 /StemV 0 /FontFile2 31 0 R >> endobj 31 0 obj << /Filter /FlateDecode /Length 5364 /Length1 9860 >> stream =:fV?| CYd= Rmr3ɯE ꇿ޳l\:^o p, &tMD%6՛}Gx:?ok A]'}bf7]VXƷ`[\׿'y.x$=JÄ`F:Y*,"&'>ea(my'Te89>,27NI|'[\CU]ev6`6ȧ@vXSѾsr/RO׋-QlӍQfCW` MqWNΑ+'02HڿJ-z}0!. :DFРQ(x-lYqC f5E{O_Fgҿ8iqr hgf<}À1D_q!HNN24\@qa.#draUڪ۵Bt0ꘄƘy`ȄKV5ᨡtvk^]JkU͇WllEWh/OijWpU='M.&e=dQvt/iQzXf`=ۿ&糧,C;Ks4S@9E⌜U~{KnL+,5}C Vc f"ZA NPBm(lTRc䟔)/ : *"^[>eI*0/pX Y|TKʚT` ~dA V6sK$s /Cc(jX 7AlLbgJdq=,Y׮3fԆ E{2ut8pXP!d`f8YM(k`9Xk<b|L3BDXP]j-G?cYqgop ㌦jfRX!U[a~Sbx:1z9\=+KDfV@+z\t7{hJ(7v(2`'!4<[p; x 9-b$"0"j௫Jkv?0lñ%*QGV"bSzɟ4O,鉨f[zOIukDkØ RN$+s})N.rS2;@oF쭗z0O/Ȉ5+_>j,(0كȥ>I1ª1ZL&C;cw$WC2B36tWcl8J 2V.'~8ac#y/^\UQ1c$wEF\w&@׳=_;3ohmI.6e"t؞FhRP69 Vzv^?fc /ڊ"і懜`f)&jlqAgr ?pt1D q$6ԏ#'`}XN}[Nǟߴ @AZ&yQ>\  &܅YPX|yj^?mϟ3uZsTӽ <>sپŠڟAd5|$2)|V*MX#]鉼|.S{Xg?MN8fjX'iˎ JyYӼpU6Cc/9>ktDty8a@[5Xl_k [ޙ-nƾCHb*n ^W=Jr$r~ãWRS3u8fXPgcڼ^'z퀠ډ2ۑjEY8 b'RV".Dg@Eh\hujxc%sE'@4g1}~_=ﯶo1 ՞V3ppB7 a)~*ΒjhV!B76%|$bjYB'J ̮/X|د7 eN2+҃@>D8LZyDg f-> wNɣ9vn0ukl. ͒$X@0[ԕ~^2LНf˵4q+u<%c(G1{9|ncAs!*Ǯ~g+ekNeTa= fv,('MgS\ mG^ tϽjYr.L+`I$U*V3+rذ=B I9p8r%e{(x *@npa F Qtr)B+8l3LRe;HĕqKL'CFN*0 ;EK,SX 1`.]y78b a=P!wA-o\oA#x#5YS뼉= hp^s@Bs} o֎=>&MXH7' *H6lRMاLΐil+QBh~ Qv^9ANj~d82'n/@(ٺ[Sel0{ -tṶH!)6<#N0b,ҩ_G2}\o4z<pOiҦHh{^x5MHǢ#˧- Q|iU%$}RC㓉a"XOj8*'\Fʋ/i\$gR$GGpjS>i#MlWp)*B&q6v+܉@E /)^*a3DCx/imݩRJKJn-‘/OeM~$aIaK/|Yp~Ê۴WrF C8jb&M'L$cqDj8 6uFR!=ߟ!DhKȓmidm=>B`D^Qv ͠7OYr3:Ac++ixu]YflX\%WeNx Fe;\JG-2[=>W Gl-Gs^+f{rFVB6L˺^1 ƨK0= s7܄NLwjUxNeHߵvgt~&6G\&D>L3g\Z=zAi6w.7 ImZ))m:>-Q$h.0QZg#=j)0{c2#$WlAqJ&v0&v j@ jeH.3Ny ArUכ7HE2b6)}0`#"5:IS5Ulof\3-XDkxg^W!(ś(iRq' >nl؜X-W`sO(ޡұ('|#6+^ȧ v IE0 i[#5q&`ayZIbuRt؍c,vq٭⁁F/&hj)ܹn~ê*מ! 7_ȷ3IMG-!g4bK0=*Lvg#Y(ڪf㬏P Q1N,Xb雬n0ir9j! 3KЇ4?JM Q0V 6_/o[jԖQ@|Goblm#v:/c/|~Kvz czq  藓OzXg- i0N =1FSMR0n)q)hS܇%jtKgԡ3[1 ӫ0qQ$ޚE ᾪ"AMrߎt3 be3rF !R ,6J[a)ZY}8InLp$ڴ('Qo*0kJQĮ铢LU}+F֋>4RLZ(kS^Cz9c8dtzri$ )#R}l[,c > endobj 33 0 obj << /Filter /FlateDecode /Length 6677 /Length1 14832 >> stream mK-?|$0:1QcgeQ]#ù (aѯ*G/Q?dpދhҝB 2ىڗ&?Yx4 9q=$̤_GS.v\c5ra}_xR&C*}-z~/>3Ƭ1WDBuEV}:(-i.A L D{G(yuhU3Ob>%Ϳ#۠` 01Vm:B Iw5yd9lx*'DX[5v0Tpo4(ȩ Ǻf3[]:mY")75B!jaڤ YuJ)yWp({LuRֹy ';5ud&9 ?%1@: D*,ZhX ]OQ1rW%t^>˱5&P] p($[0I}BxiqHSeg2]ART5jf#o=gbС!U4JH9$Bxl6|Y vq0]`"g_tK|C~[dDb[ڑ J ɦF:[7%;O4*X* y7jϥ ~V82}$7ߴ*h!#h(1+&-)-'!hVZ12 cvT͎xo@Hܒ'R 6~fu؋ܮ6;8 ! 4q׊t91am2(|4A(+YK9h˽L6_BFkش!FkO7?Y@gojpoWX!(|V3xel:4:k~ѓ6eEBMB J˵j18G3 xjoi6tYc޳2Qq>hT UQ}"qmqTVoEew$9uмҝ]^rFmň@TU ÁѿzpG_'e%&|ae(p@>z(:`DUy#cᯛ>Z4 6xr\B}~Q\jarW-5b9*op:U kNr&zJ^l=K @.=}NkNv|ҁ1+J۸,vzk='pZ?j 10ZLQLċ"q@^6P@3g^븮L'=jfd'ՔsėDXˑ2SSIjT@Ek@ ' X߄qd]sj:fՕ$0Yp]IB؜2<@(#b/C}4MGQQ];,^Gk,:bҼE<8ZzR0WT۸Mp Oq5ĸ^d>]) [yyBM+ UF(:@?,3 =?xy:SI(]]0n@FnV"q0iEErE^tw`ΫlSB|fK,2Xϡw.j+$~`x;2Y7k<zWxL喜Z&.tw!ãS xեrY.t!RDEyOF}>ah\SރK~MlO!vBH~9`K2vP@RyK< ME7Mj<2Μ.E}9v-n3oBʅ4*zG9rf(-{9+)HF:x 7z#/neJ\jdQ4•GCI1 Q+Ǖ#3eP}t++tהa a(oSҏ jbpj`qAvixBAG#lUZUw4)Qi'N"ߛ7%07lh9 O82zQn_Ȣ 1B8Yƣ8_k횞QE!2K 'DR3-bqFٱ}8#mv1uUfQ<` XRk\]ֻûv6~5m۹Sgg{ӧ̍ImQY}: ^9 qHGٓ3{',)j{c5>P;|J bˌ'z9[ c,GNs!>_ 6<F%<^ '\FaWa' MDq*K7[\k4SW;p H4(_i&l?zf+.n^=+n! /'/a̴5Y)Ul^1=e1#}&M 1p z&AZhbHyI,2ŠL!+>% l(ՍHULMDc:^Y~2x8 aOEEmZK{aЊI^^9/)jyIu,K%pI-]CuC~ b&,b%e^:k<߀]jQ߮y--B|ml?k]bg/Q.w*+1ʱEjpM.=U տ.s:YM x,RRr5K3_ սj?'gc Ж>p{E-\S#1z}ϡ\Pd ̊&x/~%u1p'I1aRl7Hl/3 ,̀0Z@޴Ϣ7㥡8K5螈sXO!E^xl Ruk23!/mpۓW?5#5cZ}Kֿm bErg's ur~5+B-LBK'Dbw{Acicrul^BLrT&>/кqH?pKuD{e#'Qi9L ÎLXJG/:P_!m l_V- y >\Ò4p& 64uw3}I8,LTbrngs+FGymJ4$<˸5 45A8 bLiM:)t^&ves%A^oiǩݭ`[1FYEvc^? }kf\|!u QVk  @ܷ Zvػas= |-EQrY)W-hLtAnEo njTppb_[Er&!s$խ4$H„7`$886ݿtGYɣ3cۄXXAGP@ %jC=u3-o'z^ĸ SS[sg&˷>\{gdxRE߁ 1Jipe [>w;^Dɾb([oU_*nɍ[[U4%ºЋ OuJ4Nf&*e wmWpÔ$I*Cf} N^`G"ռ]ZeUiTl`1S4.-U#X9v15=>#EE8T%ey8dhYvmk +"\]ݲcܠ5bJ%aS,X}h\cp4Bj4y?739s3SNB-O+90sBAY?k?n90~,9J $F{\O-羬މM ~Nrr]oPXo{3{ ,KG%t ~[!|"[~(,~M Ї?0-|0lk& y =R.]_#4"U$Ybb!M?#I,!GLu?lw]aWy-ޥ^~4+9pY]Cb[k&9cnQAFAx9J 5܆?{"%H Ö2+D5OJLnKbqȝR$<0np$Eσv~KpNNԓ_mAMȡg(, /ŇYpL -踒ڑn EMm+*%|GD㍪Y+T-,?>F57~ӄxE9 "] cMU盐7hڟu x3 u+ۂ=˵-|6xܾX_Х(hQTU< Hr eFd)i@Yq6؃8fXEb;^οrR_qRٶrbT?gzD]R@$"@W `;PQL Tg,PhL{wuo.4s}fP|PN,2UEAyr ]i,}H_~PMg=Ǯ,vS}UҰ`= '$y*rk(F;PŦz{vL8$tG7Ҋ7"?8j܅sD}Y{{FճH]xɆ@߻]=lwjIb6mi'tfO qZKShM[<@J 總-$3KpAؿSD/X6z6rRmHyiV1? Ʌ []t(@IAkX5X_L)UMpm}"F'Ɛj-O _ꐳYKbbuf `>U~exyJ=2Ʀ\{kNrJYlbͷlFV. N`aHɍOvc-Y@m'{tlyvRk<|18`ЭD̐Cnʽ[W2L6Cp& J=e;ӒAJAgVd y*=O5WVXLHZv x4([0*4(" v*N>F#ў]yr.-vU:Dk}2ftwh<`AB+m+td {[Eio*> /DW 1000 /W [ 120 [ 459 ] ] >> endobj 35 0 obj << /Filter /FlateDecode /Length 218 >> stream PĖgjEf9"3וahN3q8d RD6{G%jBMk(weǍ|(U߽@@vy49$_@GĬO\\z{ȃ,B9NtJ"yNMaP}>g?ѷs-B\2e*9H]9]1u5dN endstream endobj 36 0 obj << /Count 6 /First 37 0 R /Last 38 0 R >> endobj 37 0 obj << /Title ( ISKBvwңVM3 eVD W xڒ@U) /Dest [ 302 0 R /XYZ 0 687 null ] /Parent 36 0 R /Next 38 0 R /First 39 0 R /Last 40 0 R /Count 4 >> endobj 38 0 obj << /Title (p2Śr` u9ar<@~I&s:;n\nnIeuq{QV6uH\nK!"%g\ s[.RX܊6Ӣ) /Dest [ 13 0 R /XYZ 0 543 null ] /Parent 36 0 R /Prev 37 0 R >> endobj 39 0 obj << /Title (,4~ɕGsPWXXЭ0Lmq4> endobj 40 0 obj << /Title (s`N%MV0ƉY$d}n7\(sG\)bE9uq-*,\ *xM}"[U⢠d?F) /Dest [ 13 0 R /XYZ 0 556 null ] /Parent 37 0 R /Prev 41 0 R >> endobj 41 0 obj << /Title (5霅 #[&P~i~I8JP 41#,;weXQ3,0+#v@!\ 5Q症dA4%w) /Dest [ 10 0 R /XYZ 0 129 null ] /Parent 37 0 R /Prev 42 0 R /Next 40 0 R >> endobj 42 0 obj << /Title (|d! GnbԱ>\(v\(]E~35hcف=dF 8}@%㉴i\ xeg6= s"ߡf) /Dest [ 10 0 R /XYZ 0 543 null ] /Parent 37 0 R /Prev 39 0 R /Next 41 0 R >> endobj 43 0 obj << /S /Document /P 301 0 R /K [ 44 0 R 84 0 R ] >> endobj 44 0 obj << /S /Sect /P 43 0 R /K [ 45 0 R 46 0 R 47 0 R 48 0 R 49 0 R 50 0 R 51 0 R 52 0 R 53 0 R 54 0 R 55 0 R 56 0 R 57 0 R 58 0 R 59 0 R 60 0 R 61 0 R 62 0 R 63 0 R 64 0 R 65 0 R 66 0 R 67 0 R 68 0 R 69 0 R 70 0 R 71 0 R 72 0 R 73 0 R 74 0 R 75 0 R 76 0 R 77 0 R 78 0 R 79 0 R 80 0 R 81 0 R 82 0 R 83 0 R ] /T () >> endobj 45 0 obj << /S /P /P 44 0 R /Pg 302 0 R /T () >> endobj 46 0 obj << /S /P /P 44 0 R /Pg 302 0 R /T () >> endobj 47 0 obj << /S /P /P 44 0 R /K [ 2 ] /Pg 302 0 R >> endobj 48 0 obj << /S /P /P 44 0 R /Pg 302 0 R /T () >> endobj 49 0 obj << /S /P /P 44 0 R /Pg 302 0 R /T () >> endobj 50 0 obj << /S /P /P 44 0 R /Pg 302 0 R /T () >> endobj 51 0 obj << /S /P /P 44 0 R /Pg 302 0 R /T () >> endobj 52 0 obj << /S /P /P 44 0 R /K [ 7 ] /Pg 302 0 R >> endobj 53 0 obj << /S /P /P 44 0 R /Pg 302 0 R /T () >> endobj 54 0 obj << /S /P /P 44 0 R /K [ 9 ] /Pg 302 0 R >> endobj 55 0 obj << /S /P /P 44 0 R /K [ 10 ] /Pg 302 0 R >> endobj 56 0 obj << /S /P /P 44 0 R /K [ 11 ] /Pg 302 0 R >> endobj 57 0 obj << /S /P /P 44 0 R /Pg 302 0 R /T () >> endobj 58 0 obj << /S /P /P 44 0 R /K [ 13 ] /Pg 302 0 R >> endobj 59 0 obj << /S /P /P 44 0 R /Pg 302 0 R /T () >> endobj 60 0 obj << /S /P /P 44 0 R /K [ 15 ] /Pg 302 0 R >> endobj 61 0 obj << /S /P /P 44 0 R /Pg 302 0 R /T () >> endobj 62 0 obj << /S /P /P 44 0 R /K [ 17 ] /Pg 302 0 R >> endobj 63 0 obj << /S /P /P 44 0 R /Pg 302 0 R /T () >> endobj 64 0 obj << /S /P /P 44 0 R /K [ 19 ] /Pg 302 0 R >> endobj 65 0 obj << /S /P /P 44 0 R /Pg 302 0 R /T () >> endobj 66 0 obj << /S /P /P 44 0 R /Pg 302 0 R /T () >> endobj 67 0 obj << /S /P /P 44 0 R /Pg 302 0 R /T () >> endobj 68 0 obj << /S /P /P 44 0 R /Pg 302 0 R /T () >> endobj 69 0 obj << /S /Footnote /P 44 0 R /K [ 24 ] /Pg 302 0 R >> endobj 70 0 obj << /S /P /P 44 0 R /K [ 0 ] /Pg 1 0 R >> endobj 71 0 obj << /S /P /P 44 0 R /Pg 1 0 R /T () >> endobj 72 0 obj << /S /P /P 44 0 R /Pg 1 0 R /T () >> endobj 73 0 obj << /S /P /P 44 0 R /K [ 3 ] /Pg 1 0 R >> endobj 74 0 obj << /S /P /P 44 0 R /Pg 1 0 R /T () >> endobj 75 0 obj << /S /P /P 44 0 R /K [ 5 ] /Pg 1 0 R >> endobj 76 0 obj << /S /P /P 44 0 R /Pg 1 0 R /T () >> endobj 77 0 obj << /S /P /P 44 0 R /K [ 7 ] /Pg 1 0 R >> endobj 78 0 obj << /S /P /P 44 0 R /Pg 1 0 R /T () >> endobj 79 0 obj << /S /P /P 44 0 R /K [ 9 ] /Pg 1 0 R >> endobj 80 0 obj << /S /P /P 44 0 R /Pg 1 0 R /T () >> endobj 81 0 obj << /S /P /P 44 0 R /K [ 11 ] /Pg 1 0 R >> endobj 82 0 obj << /S /P /P 44 0 R /Pg 1 0 R /T () >> endobj 83 0 obj << /S /P /P 44 0 R /Pg 4 0 R >> endobj 84 0 obj << /S /Sect /P 43 0 R /K [ 85 0 R 86 0 R 87 0 R 88 0 R 89 0 R 90 0 R 91 0 R 92 0 R 93 0 R 94 0 R 95 0 R 96 0 R 97 0 R 98 0 R 99 0 R 100 0 R 101 0 R 102 0 R 103 0 R 104 0 R 105 0 R 106 0 R 107 0 R 108 0 R 109 0 R 110 0 R 111 0 R 112 0 R 113 0 R 114 0 R 115 0 R 116 0 R 117 0 R 118 0 R 119 0 R 120 0 R 121 0 R 122 0 R 123 0 R 124 0 R 125 0 R 126 0 R 127 0 R 128 0 R 129 0 R 130 0 R 131 0 R 132 0 R 133 0 R 134 0 R 135 0 R 136 0 R 137 0 R 138 0 R 139 0 R 140 0 R 141 0 R 142 0 R 143 0 R 144 0 R 145 0 R 146 0 R 147 0 R 148 0 R 149 0 R 150 0 R 151 0 R 152 0 R 153 0 R 154 0 R 155 0 R 156 0 R 157 0 R 158 0 R 159 0 R 160 0 R 161 0 R 162 0 R 163 0 R 164 0 R 165 0 R 166 0 R 167 0 R 168 0 R 169 0 R 170 0 R 171 0 R 172 0 R 173 0 R 174 0 R 175 0 R 176 0 R 177 0 R 178 0 R 179 0 R 180 0 R 181 0 R 182 0 R 183 0 R 184 0 R 185 0 R 186 0 R 187 0 R 188 0 R 189 0 R 190 0 R 191 0 R 192 0 R 193 0 R 194 0 R 195 0 R 196 0 R 197 0 R 198 0 R 199 0 R 200 0 R 201 0 R 202 0 R 203 0 R 204 0 R 205 0 R 206 0 R 207 0 R 208 0 R 209 0 R 210 0 R 211 0 R 212 0 R 213 0 R 214 0 R 215 0 R 216 0 R 217 0 R 218 0 R 219 0 R 220 0 R 221 0 R 222 0 R 223 0 R 224 0 R 225 0 R 226 0 R 227 0 R 228 0 R 229 0 R 230 0 R 231 0 R 232 0 R 233 0 R 234 0 R 235 0 R 236 0 R 237 0 R 238 0 R 239 0 R 240 0 R 241 0 R 242 0 R 243 0 R 244 0 R 245 0 R 246 0 R 247 0 R 248 0 R 249 0 R 250 0 R 251 0 R 252 0 R 253 0 R 254 0 R 255 0 R 256 0 R 257 0 R 258 0 R 259 0 R 260 0 R 261 0 R 262 0 R 263 0 R 264 0 R 265 0 R 266 0 R 267 0 R 268 0 R 269 0 R 270 0 R 271 0 R 272 0 R 273 0 R 274 0 R 275 0 R 276 0 R 277 0 R 278 0 R 279 0 R 280 0 R 281 0 R 282 0 R 283 0 R 284 0 R ] /T () >> endobj 85 0 obj << /S /P /P 84 0 R /K [ 1 ] /Pg 4 0 R >> endobj 86 0 obj << /S /P /P 84 0 R /Pg 4 0 R /T () >> endobj 87 0 obj << /S /P /P 84 0 R /K [ 3 ] /Pg 4 0 R >> endobj 88 0 obj << /S /P /P 84 0 R /Pg 4 0 R /T () >> endobj 89 0 obj << /S /P /P 84 0 R /K [ 5 ] /Pg 4 0 R >> endobj 90 0 obj << /S /P /P 84 0 R /Pg 4 0 R /T () >> endobj 91 0 obj << /S /P /P 84 0 R /K [ 7 ] /Pg 4 0 R >> endobj 92 0 obj << /S /P /P 84 0 R /Pg 4 0 R /T () >> endobj 93 0 obj << /S /P /P 84 0 R /K [ 9 ] /Pg 4 0 R >> endobj 94 0 obj << /S /P /P 84 0 R /Pg 4 0 R /T () >> endobj 95 0 obj << /S /P /P 84 0 R /K [ 11 ] /Pg 4 0 R >> endobj 96 0 obj << /S /P /P 84 0 R /Pg 4 0 R /T () >> endobj 97 0 obj << /S /P /P 84 0 R /K [ 13 ] /Pg 4 0 R >> endobj 98 0 obj << /S /P /P 84 0 R /Pg 4 0 R /T () >> endobj 99 0 obj << /S /P /P 84 0 R /K [ 15 ] /Pg 4 0 R >> endobj 100 0 obj << /S /P /P 84 0 R /Pg 4 0 R /T () >> endobj 101 0 obj << /S /P /P 84 0 R /K [ 17 ] /Pg 4 0 R >> endobj 102 0 obj << /S /P /P 84 0 R /Pg 4 0 R /T () >> endobj 103 0 obj << /S /P /P 84 0 R /K [ 19 ] /Pg 4 0 R >> endobj 104 0 obj << /S /P /P 84 0 R /Pg 4 0 R /T () >> endobj 105 0 obj << /S /P /P 84 0 R /K [ 21 ] /Pg 4 0 R >> endobj 106 0 obj << /S /P /P 84 0 R /Pg 4 0 R /T () >> endobj 107 0 obj << /S /P /P 84 0 R /K [ 23 ] /Pg 4 0 R >> endobj 108 0 obj << /S /P /P 84 0 R /Pg 4 0 R /T () >> endobj 109 0 obj << /S /P /P 84 0 R /K [ 25 ] /Pg 4 0 R >> endobj 110 0 obj << /S /P /P 84 0 R /Pg 4 0 R /T () >> endobj 111 0 obj << /S /P /P 84 0 R /K [ 27 ] /Pg 4 0 R >> endobj 112 0 obj << /S /P /P 84 0 R /Pg 4 0 R /T () >> endobj 113 0 obj << /S /P /P 84 0 R /K [ 29 ] /Pg 4 0 R >> endobj 114 0 obj << /S /P /P 84 0 R /Pg 4 0 R /T () >> endobj 115 0 obj << /S /P /P 84 0 R /K [ 31 ] /Pg 4 0 R >> endobj 116 0 obj << /S /P /P 84 0 R /Pg 4 0 R /T () >> endobj 117 0 obj << /S /P /P 84 0 R /K [ 33 ] /Pg 4 0 R >> endobj 118 0 obj << /S /P /P 84 0 R /Pg 4 0 R /T () >> endobj 119 0 obj << /S /P /P 84 0 R /K [ 35 ] /Pg 4 0 R >> endobj 120 0 obj << /S /P /P 84 0 R /Pg 4 0 R /T () >> endobj 121 0 obj << /S /P /P 84 0 R /Pg 4 0 R /T () >> endobj 122 0 obj << /S /P /P 84 0 R /K [ 38 ] /Pg 4 0 R >> endobj 123 0 obj << /S /P /P 84 0 R /Pg 4 0 R /T () >> endobj 124 0 obj << /S /P /P 84 0 R /K [ 40 ] /Pg 4 0 R >> endobj 125 0 obj << /S /P /P 84 0 R /Pg 4 0 R /T () >> endobj 126 0 obj << /S /P /P 84 0 R /Pg 4 0 R /T () >> endobj 127 0 obj << /S /P /P 84 0 R /K [ 43 ] /Pg 4 0 R >> endobj 128 0 obj << /S /P /P 84 0 R /Pg 4 0 R /T () >> endobj 129 0 obj << /S /P /P 84 0 R /K [ 45 ] /Pg 4 0 R >> endobj 130 0 obj << /S /P /P 84 0 R /K [ 46 ] /Pg 4 0 R >> endobj 131 0 obj << /S /P /P 84 0 R /K [ 47 ] /Pg 4 0 R >> endobj 132 0 obj << /S /P /P 84 0 R /Pg 4 0 R /T () >> endobj 133 0 obj << /S /P /P 84 0 R /K [ 49 ] /Pg 4 0 R >> endobj 134 0 obj << /S /P /P 84 0 R /Pg 4 0 R /T () >> endobj 135 0 obj << /S /P /P 84 0 R /Pg 4 0 R /T () >> endobj 136 0 obj << /S /P /P 84 0 R /Pg 4 0 R /T () >> endobj 137 0 obj << /S /P /P 84 0 R /K [ 0 ] /Pg 7 0 R >> endobj 138 0 obj << /S /P /P 84 0 R /Pg 7 0 R /T () >> endobj 139 0 obj << /S /P /P 84 0 R /K [ 2 ] /Pg 7 0 R >> endobj 140 0 obj << /S /P /P 84 0 R /Pg 7 0 R /T () >> endobj 141 0 obj << /S /P /P 84 0 R /K [ 4 ] /Pg 7 0 R >> endobj 142 0 obj << /S /P /P 84 0 R /Pg 7 0 R /T () >> endobj 143 0 obj << /S /P /P 84 0 R /K [ 6 ] /Pg 7 0 R >> endobj 144 0 obj << /S /P /P 84 0 R /Pg 7 0 R /T () >> endobj 145 0 obj << /S /P /P 84 0 R /K [ 8 ] /Pg 7 0 R >> endobj 146 0 obj << /S /P /P 84 0 R /Pg 7 0 R /T () >> endobj 147 0 obj << /S /P /P 84 0 R /Pg 7 0 R /T () >> endobj 148 0 obj << /S /P /P 84 0 R /K [ 11 ] /Pg 7 0 R >> endobj 149 0 obj << /S /P /P 84 0 R /Pg 7 0 R /T () >> endobj 150 0 obj << /S /P /P 84 0 R /K [ 13 ] /Pg 7 0 R >> endobj 151 0 obj << /S /P /P 84 0 R /Pg 7 0 R /T () >> endobj 152 0 obj << /S /P /P 84 0 R /K [ 15 ] /Pg 7 0 R >> endobj 153 0 obj << /S /P /P 84 0 R /Pg 7 0 R /T () >> endobj 154 0 obj << /S /P /P 84 0 R /K [ 17 ] /Pg 7 0 R >> endobj 155 0 obj << /S /P /P 84 0 R /Pg 7 0 R /T () >> endobj 156 0 obj << /S /P /P 84 0 R /K [ 19 ] /Pg 7 0 R >> endobj 157 0 obj << /S /P /P 84 0 R /Pg 7 0 R /T () >> endobj 158 0 obj << /S /P /P 84 0 R /K [ 21 ] /Pg 7 0 R >> endobj 159 0 obj << /S /P /P 84 0 R /K [ 22 ] /Pg 7 0 R >> endobj 160 0 obj << /S /P /P 84 0 R /K [ 23 ] /Pg 7 0 R >> endobj 161 0 obj << /S /P /P 84 0 R /Pg 7 0 R /T () >> endobj 162 0 obj << /S /P /P 84 0 R /K [ 25 ] /Pg 7 0 R >> endobj 163 0 obj << /S /P /P 84 0 R /Pg 7 0 R /T () >> endobj 164 0 obj << /S /P /P 84 0 R /K [ 27 ] /Pg 7 0 R >> endobj 165 0 obj << /S /P /P 84 0 R /K [ 28 ] /Pg 7 0 R >> endobj 166 0 obj << /S /P /P 84 0 R /Pg 7 0 R /T () >> endobj 167 0 obj << /S /P /P 84 0 R /K [ 30 ] /Pg 7 0 R >> endobj 168 0 obj << /S /P /P 84 0 R /Pg 7 0 R /T () >> endobj 169 0 obj << /S /P /P 84 0 R /K [ 32 ] /Pg 7 0 R >> endobj 170 0 obj << /S /P /P 84 0 R /K [ 33 ] /Pg 7 0 R >> endobj 171 0 obj << /S /P /P 84 0 R /K [ 34 ] /Pg 7 0 R >> endobj 172 0 obj << /S /P /P 84 0 R /Pg 7 0 R /T () >> endobj 173 0 obj << /S /P /P 84 0 R /K [ 36 ] /Pg 7 0 R >> endobj 174 0 obj << /S /P /P 84 0 R /Pg 7 0 R /T () >> endobj 175 0 obj << /S /P /P 84 0 R /K [ 38 ] /Pg 7 0 R >> endobj 176 0 obj << /S /P /P 84 0 R /Pg 7 0 R /T () >> endobj 177 0 obj << /S /P /P 84 0 R /K [ 40 ] /Pg 7 0 R >> endobj 178 0 obj << /S /P /P 84 0 R /Pg 7 0 R /T () >> endobj 179 0 obj << /S /P /P 84 0 R /K [ 42 ] /Pg 7 0 R >> endobj 180 0 obj << /S /P /P 84 0 R /Pg 7 0 R /T () >> endobj 181 0 obj << /S /P /P 84 0 R /K [ 44 << /Type /MCR /MCID 0 /Pg 10 0 R >> ] /Pg 7 0 R >> endobj 182 0 obj << /S /P /P 84 0 R /Pg 10 0 R /T () >> endobj 183 0 obj << /S /P /P 84 0 R /K [ 2 ] /Pg 10 0 R >> endobj 184 0 obj << /S /P /P 84 0 R /Pg 10 0 R /T () >> endobj 185 0 obj << /S /P /P 84 0 R /K [ 4 ] /Pg 10 0 R >> endobj 186 0 obj << /S /P /P 84 0 R /Pg 10 0 R /T () >> endobj 187 0 obj << /S /P /P 84 0 R /K [ 6 ] /Pg 10 0 R >> endobj 188 0 obj << /S /P /P 84 0 R /Pg 10 0 R /T () >> endobj 189 0 obj << /S /P /P 84 0 R /K [ 8 ] /Pg 10 0 R >> endobj 190 0 obj << /S /P /P 84 0 R /Pg 10 0 R /T () >> endobj 191 0 obj << /S /P /P 84 0 R /K [ 10 ] /Pg 10 0 R >> endobj 192 0 obj << /S /P /P 84 0 R /Pg 10 0 R /T () >> endobj 193 0 obj << /S /P /P 84 0 R /Pg 10 0 R /T () >> endobj 194 0 obj << /S /P /P 84 0 R /K [ 13 ] /Pg 10 0 R >> endobj 195 0 obj << /S /P /P 84 0 R /Pg 10 0 R /T () >> endobj 196 0 obj << /S /P /P 84 0 R /K [ 15 ] /Pg 10 0 R >> endobj 197 0 obj << /S /P /P 84 0 R /Pg 10 0 R /T () >> endobj 198 0 obj << /S /P /P 84 0 R /K [ 17 ] /Pg 10 0 R >> endobj 199 0 obj << /S /P /P 84 0 R /Pg 10 0 R /T () >> endobj 200 0 obj << /S /P /P 84 0 R /K [ 19 ] /Pg 10 0 R >> endobj 201 0 obj << /S /P /P 84 0 R /Pg 10 0 R /T () >> endobj 202 0 obj << /S /P /P 84 0 R /K [ 21 ] /Pg 10 0 R >> endobj 203 0 obj << /S /P /P 84 0 R /Pg 10 0 R /T () >> endobj 204 0 obj << /S /P /P 84 0 R /K [ 23 ] /Pg 10 0 R >> endobj 205 0 obj << /S /P /P 84 0 R /Pg 10 0 R /T () >> endobj 206 0 obj << /S /P /P 84 0 R /K [ 25 ] /Pg 10 0 R >> endobj 207 0 obj << /S /P /P 84 0 R /K [ 26 ] /Pg 10 0 R >> endobj 208 0 obj << /S /P /P 84 0 R /Pg 10 0 R /T () >> endobj 209 0 obj << /S /P /P 84 0 R /K [ 28 ] /Pg 10 0 R >> endobj 210 0 obj << /S /P /P 84 0 R /K [ 29 ] /Pg 10 0 R >> endobj 211 0 obj << /S /P /P 84 0 R /Pg 10 0 R /T () >> endobj 212 0 obj << /S /P /P 84 0 R /K [ 31 ] /Pg 10 0 R >> endobj 213 0 obj << /S /P /P 84 0 R /Pg 10 0 R /T () >> endobj 214 0 obj << /S /P /P 84 0 R /Pg 10 0 R /T () >> endobj 215 0 obj << /S /P /P 84 0 R /K [ 34 ] /Pg 10 0 R >> endobj 216 0 obj << /S /P /P 84 0 R /K [ 35 ] /Pg 10 0 R >> endobj 217 0 obj << /S /P /P 84 0 R /Pg 10 0 R /T () >> endobj 218 0 obj << /S /P /P 84 0 R /K [ 37 ] /Pg 10 0 R >> endobj 219 0 obj << /S /P /P 84 0 R /Pg 10 0 R /T () >> endobj 220 0 obj << /S /P /P 84 0 R /K [ 39 ] /Pg 10 0 R >> endobj 221 0 obj << /S /P /P 84 0 R /Pg 10 0 R /T () >> endobj 222 0 obj << /S /P /P 84 0 R /Pg 10 0 R /T () >> endobj 223 0 obj << /S /P /P 84 0 R /K [ 42 ] /Pg 10 0 R >> endobj 224 0 obj << /S /P /P 84 0 R /Pg 10 0 R /T () >> endobj 225 0 obj << /S /P /P 84 0 R /K [ 44 ] /Pg 10 0 R >> endobj 226 0 obj << /S /P /P 84 0 R /Pg 10 0 R /T () >> endobj 227 0 obj << /S /P /P 84 0 R /K [ 46 << /Type /MCR /MCID 0 /Pg 13 0 R >> ] /Pg 10 0 R >> endobj 228 0 obj << /S /P /P 84 0 R /Pg 13 0 R /T () >> endobj 229 0 obj << /S /P /P 84 0 R /Pg 13 0 R /T () >> endobj 230 0 obj << /S /P /P 84 0 R /K [ 3 ] /Pg 13 0 R >> endobj 231 0 obj << /S /P /P 84 0 R /Pg 13 0 R /T () >> endobj 232 0 obj << /S /P /P 84 0 R /K [ 5 ] /Pg 13 0 R >> endobj 233 0 obj << /S /P /P 84 0 R /Pg 13 0 R /T () >> endobj 234 0 obj << /S /P /P 84 0 R /K [ 7 ] /Pg 13 0 R >> endobj 235 0 obj << /S /P /P 84 0 R /Pg 13 0 R /T () >> endobj 236 0 obj << /S /P /P 84 0 R /K [ 9 ] /Pg 13 0 R >> endobj 237 0 obj << /S /P /P 84 0 R /Pg 13 0 R /T () >> endobj 238 0 obj << /S /P /P 84 0 R /K [ 11 ] /Pg 13 0 R >> endobj 239 0 obj << /S /P /P 84 0 R /Pg 13 0 R /T () >> endobj 240 0 obj << /S /P /P 84 0 R /K [ 13 ] /Pg 13 0 R >> endobj 241 0 obj << /S /P /P 84 0 R /Pg 13 0 R /T () >> endobj 242 0 obj << /S /P /P 84 0 R /K [ 15 ] /Pg 13 0 R >> endobj 243 0 obj << /S /P /P 84 0 R /Pg 13 0 R /T () >> endobj 244 0 obj << /S /P /P 84 0 R /Pg 13 0 R /T () >> endobj 245 0 obj << /S /P /P 84 0 R /K [ 18 ] /Pg 13 0 R >> endobj 246 0 obj << /S /P /P 84 0 R /Pg 13 0 R /T () >> endobj 247 0 obj << /S /P /P 84 0 R /K [ 20 ] /Pg 13 0 R >> endobj 248 0 obj << /S /P /P 84 0 R /Pg 13 0 R /T () >> endobj 249 0 obj << /S /P /P 84 0 R /K [ 22 ] /Pg 13 0 R >> endobj 250 0 obj << /S /P /P 84 0 R /Pg 13 0 R /T () >> endobj 251 0 obj << /S /P /P 84 0 R /Pg 13 0 R /T () >> endobj 252 0 obj << /S /P /P 84 0 R /K [ 25 ] /Pg 13 0 R >> endobj 253 0 obj << /S /P /P 84 0 R /Pg 13 0 R /T () >> endobj 254 0 obj << /S /P /P 84 0 R /K [ 27 ] /Pg 13 0 R >> endobj 255 0 obj << /S /P /P 84 0 R /Pg 13 0 R /T () >> endobj 256 0 obj << /S /P /P 84 0 R /K [ 29 ] /Pg 13 0 R >> endobj 257 0 obj << /S /P /P 84 0 R /Pg 13 0 R /T () >> endobj 258 0 obj << /S /P /P 84 0 R /K [ 31 ] /Pg 13 0 R >> endobj 259 0 obj << /S /P /P 84 0 R /Pg 13 0 R /T () >> endobj 260 0 obj << /S /P /P 84 0 R /K [ 33 << /Type /MCR /MCID 0 /Pg 16 0 R >> ] /Pg 13 0 R >> endobj 261 0 obj << /S /P /P 84 0 R /Pg 16 0 R /T () >> endobj 262 0 obj << /S /P /P 84 0 R /K [ 2 ] /Pg 16 0 R >> endobj 263 0 obj << /S /P /P 84 0 R /Pg 16 0 R /T () >> endobj 264 0 obj << /S /P /P 84 0 R /K [ 4 ] /Pg 16 0 R >> endobj 265 0 obj << /S /P /P 84 0 R /Pg 16 0 R /T () >> endobj 266 0 obj << /S /P /P 84 0 R /K [ 6 ] /Pg 16 0 R >> endobj 267 0 obj << /S /P /P 84 0 R /Pg 16 0 R /T () >> endobj 268 0 obj << /S /P /P 84 0 R /Pg 16 0 R /T () >> endobj 269 0 obj << /S /P /P 84 0 R /Pg 16 0 R /T () >> endobj 270 0 obj << /S /P /P 84 0 R /K [ 10 ] /Pg 16 0 R >> endobj 271 0 obj << /S /P /P 84 0 R /Pg 16 0 R /T () >> endobj 272 0 obj << /S /P /P 84 0 R /K [ 12 ] /Pg 16 0 R >> endobj 273 0 obj << /S /P /P 84 0 R /Pg 16 0 R /T () >> endobj 274 0 obj << /S /P /P 84 0 R /K [ 14 ] /Pg 16 0 R >> endobj 275 0 obj << /S /P /P 84 0 R /Pg 16 0 R /T () >> endobj 276 0 obj << /S /P /P 84 0 R /K [ 16 ] /Pg 16 0 R >> endobj 277 0 obj << /S /P /P 84 0 R /Pg 16 0 R /T () >> endobj 278 0 obj << /S /P /P 84 0 R /Pg 16 0 R /T () >> endobj 279 0 obj << /S /P /P 84 0 R /Pg 16 0 R /T () >> endobj 280 0 obj << /S /P /P 84 0 R /K [ 20 ] /Pg 16 0 R >> endobj 281 0 obj << /S /P /P 84 0 R /Pg 16 0 R /T () >> endobj 282 0 obj << /S /P /P 84 0 R /K [ 22 ] /Pg 16 0 R >> endobj 283 0 obj << /S /P /P 84 0 R /Pg 16 0 R /T () >> endobj 284 0 obj << /S /P /P 84 0 R /K [ 24 ] /Pg 16 0 R >> endobj 285 0 obj [ null null 47 0 R null null null null 52 0 R null 54 0 R 55 0 R 56 0 R null 58 0 R null 60 0 R null 62 0 R null 64 0 R null null null null 69 0 R ] endobj 286 0 obj [ 70 0 R null null 73 0 R null 75 0 R null 77 0 R null 79 0 R null 81 0 R null ] endobj 287 0 obj [ null 85 0 R null 87 0 R null 89 0 R null 91 0 R null 93 0 R null 95 0 R null 97 0 R null 99 0 R null 101 0 R null 103 0 R null 105 0 R null 107 0 R null 109 0 R null 111 0 R null 113 0 R null 115 0 R null 117 0 R null 119 0 R null null 122 0 R null 124 0 R null null 127 0 R null 129 0 R 130 0 R 131 0 R null 133 0 R null null null ] endobj 288 0 obj [ 137 0 R null 139 0 R null 141 0 R null 143 0 R null 145 0 R null null 148 0 R null 150 0 R null 152 0 R null 154 0 R null 156 0 R null 158 0 R 159 0 R 160 0 R null 162 0 R null 164 0 R 165 0 R null 167 0 R null 169 0 R 170 0 R 171 0 R null 173 0 R null 175 0 R null 177 0 R null 179 0 R null 181 0 R ] endobj 289 0 obj [ 181 0 R null 183 0 R null 185 0 R null 187 0 R null 189 0 R null 191 0 R null null 194 0 R null 196 0 R null 198 0 R null 200 0 R null 202 0 R null 204 0 R null 206 0 R 207 0 R null 209 0 R 210 0 R null 212 0 R null null 215 0 R 216 0 R null 218 0 R null 220 0 R null null 223 0 R null 225 0 R null 227 0 R ] endobj 290 0 obj [ 227 0 R null null 230 0 R null 232 0 R null 234 0 R null 236 0 R null 238 0 R null 240 0 R null 242 0 R null null 245 0 R null 247 0 R null 249 0 R null null 252 0 R null 254 0 R null 256 0 R null 258 0 R null 260 0 R ] endobj 291 0 obj [ 260 0 R null 262 0 R null 264 0 R null 266 0 R null null null 270 0 R null 272 0 R null 274 0 R null 276 0 R null null null 280 0 R null 282 0 R null 284 0 R ] endobj 292 0 obj << /Nums [ 1 285 0 R 2 286 0 R 3 287 0 R 4 288 0 R 5 289 0 R 6 290 0 R 7 291 0 R ] >> endobj 293 0 obj << /S /D >> endobj 294 0 obj << /Nums [ 0 293 0 R ] >> endobj 295 0 obj << /Producer (T1 lpQXS`]\rGG,x) /Author (thY) /Creator (T1 l]daZwCS0) /ModDate (\rn^{w+OG1T) /Title (7") /CreationDate (\rn^{w+OA\n7) >> endobj 296 0 obj << /Type /Pages /Kids [ 302 0 R 1 0 R 4 0 R 7 0 R 10 0 R 13 0 R 16 0 R ] /Count 7 >> endobj 297 0 obj << /Type /Metadata /Subtype /XML /Length 1305 >> stream A&g3Br:F75|P'8MA$/i7&GH҈Bcv(z[% =׫nhuonͦ3y0զR-; |u뤗EhwR)FɃ*iU1ZzN`KAnsC}#j-u6*E(k>%[h4hk6%hbRnᭊΏ+HҦq&G%FfzBK#K}ymzzdELu>L,Y6:!-ٷ?4 ˋgo?HTԧ[E\H>{(RE=&:C nh;C;j?!5 i* 88rLڽg{vd>|gSP ǙIHDi8M |A*ɾ­ψ%6f  "8#;Tr {M$2RAl,0# tJi+)˿a27D+h"E sB3Ǚ4G茶  K)6wڔ1yjUd58P ͠dDA#ȝXDapJ Qk:U]!H|LJ_79%K -)Re*=d Tm:BXY֬oi$:ܯY0n!Μ)OgW?b!AgȩwT$ 7z|)[.JmqEM6uB۲G#͸-Y_-dlN㑝 #\>6Lw6>T8ň&Њ8CŘ6m'ފ%oPsyk1w}FycwxU|_1nAoO<>iΫE"h dz s}-:(lͻNJC7>cLǿyRNԊGI b%3dmX휔_-K{T_ 'ʘ-H]>ρ%xB vɄxu!V4-Bh R endstream endobj xref 0 298 0000000000 65535 f 0000098243 00000 n 0000098413 00000 n 0000098590 00000 n 0000100492 00000 n 0000100662 00000 n 0000100853 00000 n 0000104597 00000 n 0000104767 00000 n 0000104972 00000 n 0000108383 00000 n 0000108556 00000 n 0000108788 00000 n 0000112386 00000 n 0000112559 00000 n 0000112778 00000 n 0000116960 00000 n 0000117133 00000 n 0000117312 00000 n 0000119673 00000 n 0000119870 00000 n 0000120023 00000 n 0000120203 00000 n 0000120396 00000 n 0000120595 00000 n 0000120821 00000 n 0000126312 00000 n 0000126517 00000 n 0000133179 00000 n 0000133384 00000 n 0000140303 00000 n 0000140523 00000 n 0000145977 00000 n 0000146205 00000 n 0000152973 00000 n 0000153189 00000 n 0000153482 00000 n 0000153545 00000 n 0000153726 00000 n 0000153927 00000 n 0000154126 00000 n 0000154323 00000 n 0000154532 00000 n 0000154746 00000 n 0000154818 00000 n 0000155153 00000 n 0000155214 00000 n 0000155275 00000 n 0000155340 00000 n 0000155401 00000 n 0000155462 00000 n 0000155523 00000 n 0000155584 00000 n 0000155649 00000 n 0000155710 00000 n 0000155775 00000 n 0000155841 00000 n 0000155907 00000 n 0000155968 00000 n 0000156034 00000 n 0000156095 00000 n 0000156161 00000 n 0000156222 00000 n 0000156288 00000 n 0000156349 00000 n 0000156415 00000 n 0000156476 00000 n 0000156537 00000 n 0000156598 00000 n 0000156659 00000 n 0000156732 00000 n 0000156795 00000 n 0000156854 00000 n 0000156913 00000 n 0000156976 00000 n 0000157035 00000 n 0000157098 00000 n 0000157157 00000 n 0000157220 00000 n 0000157279 00000 n 0000157342 00000 n 0000157401 00000 n 0000157465 00000 n 0000157524 00000 n 0000157577 00000 n 0000159245 00000 n 0000159308 00000 n 0000159367 00000 n 0000159430 00000 n 0000159489 00000 n 0000159552 00000 n 0000159611 00000 n 0000159674 00000 n 0000159733 00000 n 0000159796 00000 n 0000159855 00000 n 0000159919 00000 n 0000159978 00000 n 0000160042 00000 n 0000160101 00000 n 0000160165 00000 n 0000160225 00000 n 0000160290 00000 n 0000160350 00000 n 0000160415 00000 n 0000160475 00000 n 0000160540 00000 n 0000160600 00000 n 0000160665 00000 n 0000160725 00000 n 0000160790 00000 n 0000160850 00000 n 0000160915 00000 n 0000160975 00000 n 0000161040 00000 n 0000161100 00000 n 0000161165 00000 n 0000161225 00000 n 0000161290 00000 n 0000161350 00000 n 0000161415 00000 n 0000161475 00000 n 0000161535 00000 n 0000161600 00000 n 0000161660 00000 n 0000161725 00000 n 0000161785 00000 n 0000161845 00000 n 0000161910 00000 n 0000161970 00000 n 0000162035 00000 n 0000162100 00000 n 0000162165 00000 n 0000162225 00000 n 0000162290 00000 n 0000162350 00000 n 0000162410 00000 n 0000162470 00000 n 0000162534 00000 n 0000162594 00000 n 0000162658 00000 n 0000162718 00000 n 0000162782 00000 n 0000162842 00000 n 0000162906 00000 n 0000162966 00000 n 0000163030 00000 n 0000163090 00000 n 0000163150 00000 n 0000163215 00000 n 0000163275 00000 n 0000163340 00000 n 0000163400 00000 n 0000163465 00000 n 0000163525 00000 n 0000163590 00000 n 0000163650 00000 n 0000163715 00000 n 0000163775 00000 n 0000163840 00000 n 0000163905 00000 n 0000163970 00000 n 0000164030 00000 n 0000164095 00000 n 0000164155 00000 n 0000164220 00000 n 0000164285 00000 n 0000164345 00000 n 0000164410 00000 n 0000164470 00000 n 0000164535 00000 n 0000164600 00000 n 0000164665 00000 n 0000164725 00000 n 0000164790 00000 n 0000164850 00000 n 0000164915 00000 n 0000164975 00000 n 0000165040 00000 n 0000165100 00000 n 0000165165 00000 n 0000165225 00000 n 0000165326 00000 n 0000165387 00000 n 0000165452 00000 n 0000165513 00000 n 0000165578 00000 n 0000165639 00000 n 0000165704 00000 n 0000165765 00000 n 0000165830 00000 n 0000165891 00000 n 0000165957 00000 n 0000166018 00000 n 0000166079 00000 n 0000166145 00000 n 0000166206 00000 n 0000166272 00000 n 0000166333 00000 n 0000166399 00000 n 0000166460 00000 n 0000166526 00000 n 0000166587 00000 n 0000166653 00000 n 0000166714 00000 n 0000166780 00000 n 0000166841 00000 n 0000166907 00000 n 0000166973 00000 n 0000167034 00000 n 0000167100 00000 n 0000167166 00000 n 0000167227 00000 n 0000167293 00000 n 0000167354 00000 n 0000167415 00000 n 0000167481 00000 n 0000167547 00000 n 0000167608 00000 n 0000167674 00000 n 0000167735 00000 n 0000167801 00000 n 0000167862 00000 n 0000167923 00000 n 0000167989 00000 n 0000168050 00000 n 0000168116 00000 n 0000168177 00000 n 0000168279 00000 n 0000168340 00000 n 0000168401 00000 n 0000168466 00000 n 0000168527 00000 n 0000168592 00000 n 0000168653 00000 n 0000168718 00000 n 0000168779 00000 n 0000168844 00000 n 0000168905 00000 n 0000168971 00000 n 0000169032 00000 n 0000169098 00000 n 0000169159 00000 n 0000169225 00000 n 0000169286 00000 n 0000169347 00000 n 0000169413 00000 n 0000169474 00000 n 0000169540 00000 n 0000169601 00000 n 0000169667 00000 n 0000169728 00000 n 0000169789 00000 n 0000169855 00000 n 0000169916 00000 n 0000169982 00000 n 0000170043 00000 n 0000170109 00000 n 0000170170 00000 n 0000170236 00000 n 0000170297 00000 n 0000170399 00000 n 0000170460 00000 n 0000170525 00000 n 0000170586 00000 n 0000170651 00000 n 0000170712 00000 n 0000170777 00000 n 0000170838 00000 n 0000170899 00000 n 0000170960 00000 n 0000171026 00000 n 0000171087 00000 n 0000171153 00000 n 0000171214 00000 n 0000171280 00000 n 0000171341 00000 n 0000171407 00000 n 0000171468 00000 n 0000171529 00000 n 0000171590 00000 n 0000171656 00000 n 0000171717 00000 n 0000171783 00000 n 0000171844 00000 n 0000171910 00000 n 0000172080 00000 n 0000172181 00000 n 0000172541 00000 n 0000172868 00000 n 0000173202 00000 n 0000173446 00000 n 0000173629 00000 n 0000173736 00000 n 0000173768 00000 n 0000173814 00000 n 0000174036 00000 n 0000174143 00000 n trailer << /Size 298 /ID[<9259eeec511b9ee72fbc2184871740b6>] >> startxref 173 %%EOF vldocking_2.1.4/build.xml0000644000175000017500000001016410573516344015351 0ustar twernertwerner © Copyright 2004-2006 VLSolutions. All Rights Reserved.
www.vlsolutions.com : Java Components - Smart Client Applications
]]>