replaced <code></code> with more concise {@code}
[idea/community.git] / platform / platform-impl / src / com / intellij / openapi / wm / impl / WindowInfoImpl.java
1 /*
2  * Copyright 2000-2017 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.intellij.openapi.wm.impl;
17
18 import com.intellij.openapi.util.Comparing;
19 import com.intellij.openapi.util.JDOMExternalizable;
20 import com.intellij.openapi.wm.*;
21 import org.jdom.Element;
22 import org.jetbrains.annotations.NonNls;
23 import org.jetbrains.annotations.NotNull;
24
25 import java.awt.*;
26
27 /**
28  * @author Anton Katilin
29  * @author Vladimir Kondratyev
30  */
31 public final class WindowInfoImpl implements Cloneable, JDOMExternalizable, WindowInfo {
32   /**
33    * XML tag.
34    */
35   @NonNls static final String TAG = "window_info";
36   /**
37    * Default window weight.
38    */
39   static final float DEFAULT_WEIGHT = 0.33f;
40   private static final float DEFAULT_SIDE_WEIGHT = 0.5f;
41
42   private boolean myActive;
43   @NotNull
44   private ToolWindowAnchor myAnchor = ToolWindowAnchor.LEFT;
45   private boolean myAutoHide;
46   /**
47    * Bounds of window in "floating" mode. It equals to {@code null} if
48    * floating bounds are undefined.
49    */
50   private Rectangle myFloatingBounds;
51   private String myId;
52   private ToolWindowType myInternalType;
53   private ToolWindowType myType;
54   private boolean myVisible;
55   private boolean myShowStripeButton = true;
56   private float myWeight = DEFAULT_WEIGHT;
57   private float mySideWeight = DEFAULT_SIDE_WEIGHT;
58   private boolean mySplitMode;
59
60   @NotNull private ToolWindowContentUiType myContentUiType = ToolWindowContentUiType.TABBED;
61   /**
62    * Defines order of tool window button inside the stripe.
63    * The default value is {@code -1}.
64    */
65   private int myOrder = -1;
66   @NonNls private static final String ID_ATTR = "id";
67   @NonNls private static final String ACTIVE_ATTR = "active";
68   @NonNls private static final String ANCHOR_ATTR = "anchor";
69   @NonNls private static final String AUTOHIDE_ATTR = "auto_hide";
70   @NonNls private static final String INTERNAL_TYPE_ATTR = "internal_type";
71   @NonNls private static final String TYPE_ATTR = "type";
72   @NonNls private static final String VISIBLE_ATTR = "visible";
73   @NonNls private static final String WEIGHT_ATTR = "weight";
74   @NonNls private static final String SIDE_WEIGHT_ATTR = "sideWeight";
75   @NonNls private static final String ORDER_ATTR = "order";
76   @NonNls private static final String SIDE_TOOL_ATTR = "side_tool";
77   @NonNls private static final String CONTENT_UI_ATTR = "content_ui";
78   @NonNls private static final String SHOW_STRIPE_BUTTON = "show_stripe_button";
79
80
81   private boolean myWasRead;
82
83   /**
84    * Creates {@code WindowInfo} for tool window with specified {@code ID}.
85    */
86   WindowInfoImpl(@NotNull String id) {
87     myId = id;
88     setType(ToolWindowType.DOCKED);
89   }
90
91   /**
92    * Creates copy of {@code WindowInfo} object.
93    */
94   @NotNull
95   public WindowInfoImpl copy() {
96     try {
97       WindowInfoImpl info = (WindowInfoImpl)clone();
98       if (myFloatingBounds != null) {
99         info.myFloatingBounds = (Rectangle)myFloatingBounds.clone();
100       }
101       return info;
102     }
103     catch (CloneNotSupportedException e) {
104       throw new RuntimeException(e);
105     }
106   }
107
108   /**
109    * Copies all data from the passed {@code WindowInfo} into itself.
110    */
111   void copyFrom(@NotNull WindowInfoImpl info){
112     myActive = info.myActive;
113     myAnchor = info.myAnchor;
114     myAutoHide = info.myAutoHide;
115     myFloatingBounds = info.myFloatingBounds == null ? null : (Rectangle)info.myFloatingBounds.clone();
116     myId = info.myId;
117     setTypeAndCheck(info.myType);
118     myInternalType = info.myInternalType;
119     myVisible = info.myVisible;
120     myWeight = info.myWeight;
121     mySideWeight = info.mySideWeight;
122     myOrder = info.myOrder;
123     mySplitMode = info.mySplitMode;
124     myContentUiType = info.myContentUiType;
125   }
126
127   /**
128    * @return tool window's anchor in internal mode.
129    */
130   @NotNull
131   @Override
132   public ToolWindowAnchor getAnchor(){
133     return myAnchor;
134   }
135
136   @NotNull
137   @Override
138   public ToolWindowContentUiType getContentUiType() {
139     return myContentUiType;
140   }
141
142   void setContentUiType(@NotNull ToolWindowContentUiType type) {
143     myContentUiType = type;
144   }
145
146   /**
147    * @return bound of tool window in floating mode.
148    */
149   @Override
150   public Rectangle getFloatingBounds(){
151     return myFloatingBounds != null ? new Rectangle(myFloatingBounds) : null;
152   }
153
154   /**
155    * @return {@code ID} of the tool window.
156    */
157   @NotNull
158   String getId(){
159     return myId;
160   }
161
162   /**
163    * @return type of the tool window in internal (docked or sliding) mode. Actually the tool
164    * window can be in floating mode, but this method has sense if you want to know what type
165    * tool window had when it was internal one. The method never returns {@code null}.
166    */
167   @NotNull
168   ToolWindowType getInternalType(){
169     return myInternalType;
170   }
171
172   /**
173    * @return current type of tool window.
174    * @see ToolWindowType#DOCKED
175    * @see ToolWindowType#FLOATING
176    * @see ToolWindowType#SLIDING
177    */
178   @Override
179   public ToolWindowType getType(){
180     return myType;
181   }
182
183   /**
184    * @return internal weight of tool window. "weigth" means how much of internal desktop
185    * area the tool window is occupied. The weight has sense if the tool window is docked or
186    * sliding.
187    */
188   float getWeight(){
189     return myWeight;
190   }
191
192   float getSideWeight() {
193     return mySideWeight;
194   }
195
196   public int getOrder(){
197     return myOrder;
198   }
199
200   public void setOrder(final int order){
201     myOrder=order;
202   }
203
204   @Override
205   public boolean isActive(){
206     return myActive;
207   }
208
209   @Override
210   public boolean isAutoHide(){
211     return myAutoHide;
212   }
213
214   @Override
215   public boolean isDocked(){
216     return ToolWindowType.DOCKED==myType;
217   }
218
219   @Override
220   public boolean isFloating(){
221     return ToolWindowType.FLOATING==myType;
222   }
223
224   @Override
225   public boolean isWindowed(){
226     return ToolWindowType.WINDOWED==myType;
227   }
228
229   @Override
230   public boolean isSliding(){
231     return ToolWindowType.SLIDING==myType;
232   }
233
234   boolean isVisible(){
235     return myVisible;
236   }
237
238   @Override
239   public boolean isShowStripeButton() {
240     return myShowStripeButton;
241   }
242
243   void setShowStripeButton(boolean showStripeButton) {
244     myShowStripeButton = showStripeButton;
245   }
246
247   @Override
248   public boolean isSplit() {
249     return mySplitMode;
250   }
251
252   public void setSplit(final boolean sideTool) {
253     mySplitMode =sideTool;
254   }
255
256   @Override
257   @SuppressWarnings("EmptyCatchBlock")
258   public void readExternal(final Element element) {
259     myId = element.getAttributeValue(ID_ATTR);
260     myWasRead = true;
261     myActive = Boolean.parseBoolean(element.getAttributeValue(ACTIVE_ATTR)) && canActivateOnStart(myId);
262     try {
263       myAnchor = ToolWindowAnchor.fromText(element.getAttributeValue(ANCHOR_ATTR));
264     }
265     catch (IllegalArgumentException ignored) {
266     }
267     myAutoHide = Boolean.parseBoolean(element.getAttributeValue(AUTOHIDE_ATTR));
268     try {
269       myInternalType = ToolWindowType.valueOf(element.getAttributeValue(INTERNAL_TYPE_ATTR));
270     }
271     catch (IllegalArgumentException ignored) {
272     }
273     try {
274       setTypeAndCheck(ToolWindowType.valueOf(element.getAttributeValue(TYPE_ATTR)));
275     }
276     catch (IllegalArgumentException ignored) {
277     }
278     myVisible = Boolean.parseBoolean(element.getAttributeValue(VISIBLE_ATTR)) && canActivateOnStart(myId);
279     if (element.getAttributeValue(SHOW_STRIPE_BUTTON) != null) {
280       myShowStripeButton = Boolean.parseBoolean(element.getAttributeValue(SHOW_STRIPE_BUTTON));
281     }
282     try {
283       myWeight = Float.parseFloat(element.getAttributeValue(WEIGHT_ATTR));
284     }
285     catch (NumberFormatException ignored) {
286     }
287     try {
288       String value = element.getAttributeValue(SIDE_WEIGHT_ATTR);
289       if (value != null) {
290         mySideWeight = Float.parseFloat(value);
291       }
292     }
293     catch (NumberFormatException ignored) {
294     }
295     try {
296       myOrder = Integer.parseInt(element.getAttributeValue(ORDER_ATTR));
297     }
298     catch (NumberFormatException ignored) {
299     }
300     myFloatingBounds = ProjectFrameBoundsKt.deserializeBounds(element);
301     mySplitMode = Boolean.parseBoolean(element.getAttributeValue(SIDE_TOOL_ATTR));
302
303     myContentUiType = ToolWindowContentUiType.getInstance(element.getAttributeValue(CONTENT_UI_ATTR));
304   }
305
306   private static boolean canActivateOnStart(String id) {
307     for (ToolWindowEP ep : ToolWindowEP.EP_NAME.getExtensions()) {
308       if (id.equals(ep.id)) {
309         ToolWindowFactory factory = ep.getToolWindowFactory();
310         return !factory.isDoNotActivateOnStart();
311       }
312     }
313     return true;
314   }
315
316   /**
317    * Sets new anchor.
318    */
319   void setAnchor(@NotNull final ToolWindowAnchor anchor){
320     myAnchor=anchor;
321   }
322
323   void setActive(final boolean active){
324     myActive=active;
325   }
326
327   void setAutoHide(final boolean autoHide){
328     myAutoHide=autoHide;
329   }
330
331   void setFloatingBounds(final Rectangle floatingBounds){
332     myFloatingBounds=floatingBounds;
333   }
334
335   void setType(@NotNull final ToolWindowType type){
336     if(ToolWindowType.DOCKED==type||ToolWindowType.SLIDING==type){
337       myInternalType=type;
338     }
339     setTypeAndCheck(type);
340   }
341   //Hardcoded to avoid single-usage-API
342   private void setTypeAndCheck(@NotNull ToolWindowType type) {
343     myType = ToolWindowId.PREVIEW == myId && type == ToolWindowType.DOCKED ? ToolWindowType.SLIDING : type;
344   }
345
346   void setVisible(final boolean visible){
347     myVisible=visible;
348   }
349
350   /**
351    * Sets window weight and adjust it to [0..1] range if necessary.
352    */
353   void setWeight(float weight){
354     myWeight = Math.max(0, Math.min(1, weight));
355   }
356
357   void setSideWeight(float weight){
358     mySideWeight = Math.max(0, Math.min(1, weight));
359   }
360
361   @Override
362   public void writeExternal(final Element element){
363     element.setAttribute(ID_ATTR,myId);
364     element.setAttribute(ACTIVE_ATTR, Boolean.toString(myActive));
365     element.setAttribute(ANCHOR_ATTR,myAnchor.toString());
366     element.setAttribute(AUTOHIDE_ATTR, Boolean.toString(myAutoHide));
367     element.setAttribute(INTERNAL_TYPE_ATTR,myInternalType.toString());
368     element.setAttribute(TYPE_ATTR,myType.toString());
369     element.setAttribute(VISIBLE_ATTR, Boolean.toString(myVisible));
370     element.setAttribute(SHOW_STRIPE_BUTTON, Boolean.toString(myShowStripeButton));
371     element.setAttribute(WEIGHT_ATTR,Float.toString(myWeight));
372     element.setAttribute(SIDE_WEIGHT_ATTR, Float.toString(mySideWeight));
373     element.setAttribute(ORDER_ATTR,Integer.toString(myOrder));
374     element.setAttribute(SIDE_TOOL_ATTR, Boolean.toString(mySplitMode));
375     element.setAttribute(CONTENT_UI_ATTR, myContentUiType.getName());
376
377     if (myFloatingBounds != null) {
378       ProjectFrameBoundsKt.serializeBounds(myFloatingBounds, element);
379     }
380   }
381
382   public boolean equals(final Object obj){
383     if(!(obj instanceof WindowInfoImpl)){
384       return false;
385     }
386     final WindowInfoImpl info=(WindowInfoImpl)obj;
387     return myActive == info.myActive &&
388            myAnchor == info.myAnchor &&
389            myId.equals(info.myId) &&
390            myAutoHide == info.myAutoHide &&
391            Comparing.equal(myFloatingBounds, info.myFloatingBounds) &&
392            myInternalType == info.myInternalType &&
393            myType == info.myType &&
394            myVisible == info.myVisible &&
395            myShowStripeButton == info.myShowStripeButton &&
396            myWeight == info.myWeight &&
397            mySideWeight == info.mySideWeight &&
398            myOrder == info.myOrder &&
399            mySplitMode == info.mySplitMode &&
400           myContentUiType == info.myContentUiType;
401   }
402
403   public int hashCode(){
404     return myAnchor.hashCode()+myId.hashCode()+myType.hashCode()+myOrder;
405   }
406
407   @SuppressWarnings("HardCodedStringLiteral")
408   public String toString(){
409     return getClass().getName() + "[myId=" + myId
410            + "; myVisible=" + myVisible
411            + "; myShowStripeButton=" + myShowStripeButton
412            + "; myActive=" + myActive
413            + "; myAnchor=" + myAnchor
414            + "; myOrder=" + myOrder
415            + "; myAutoHide=" + myAutoHide
416            + "; myWeight=" + myWeight
417            + "; mySideWeight=" + mySideWeight
418            + "; myType=" + myType
419            + "; myInternalType=" + myInternalType
420            + "; myFloatingBounds=" + myFloatingBounds
421            + "; mySplitMode=" + mySplitMode
422            + "; myContentUiType=" + myContentUiType.getName() +
423            ']';
424   }
425
426   boolean wasRead() {
427     return myWasRead;
428   }
429 }