blob: d31cf367ed178c8211507e27cfcaba5781ec00cc [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.core.windows;
import org.netbeans.core.windows.model.ModelElement;
import org.openide.windows.TopComponent;
import java.awt.*;
import java.util.*;
import java.util.List;
/**
* Snapshot of split structure in model.
*
* @author Peter Zavadsky
*/
public class ModeStructureSnapshot {
private final ElementSnapshot splitRootSnapshot;
private final Set<ModeSnapshot> separateModeSnapshots;
private final Set<SlidingModeSnapshot> slidingModeSnapshots;
/** Creates a new instance of ModesModelSnapshot. */
public ModeStructureSnapshot(ElementSnapshot splitRootSnapshot,
Set<ModeSnapshot> separateModeSnapshots,
Set<SlidingModeSnapshot> slidingModeSnapshots) {
this.splitRootSnapshot = splitRootSnapshot;
this.separateModeSnapshots = separateModeSnapshots;
this.slidingModeSnapshots = slidingModeSnapshots;
}
public ElementSnapshot getSplitRootSnapshot() {
return splitRootSnapshot;
}
public ModeSnapshot[] getSeparateModeSnapshots() {
return separateModeSnapshots.toArray(new ModeSnapshot[0]);
}
public SlidingModeSnapshot[] getSlidingModeSnapshots() {
return slidingModeSnapshots.toArray(new SlidingModeSnapshot[0]);
}
/** @param name name of mode */
public ModeSnapshot findModeSnapshot(String name) {
ModeSnapshot ma = findModeSnapshotOfName(splitRootSnapshot, name);
if(ma != null) {
return ma;
}
for(Iterator it = separateModeSnapshots.iterator(); it.hasNext(); ) {
ma = (ModeSnapshot)it.next();
if(name.equals(ma.getName())) {
return ma;
}
}
for(Iterator it = slidingModeSnapshots.iterator(); it.hasNext(); ) {
ma = (SlidingModeSnapshot)it.next();
if(name.equals(ma.getName())) {
return ma;
}
}
return null;
}
private static ModeSnapshot findModeSnapshotOfName(ElementSnapshot snapshot, String name) {
if(snapshot instanceof ModeSnapshot) {
ModeSnapshot ma = (ModeSnapshot)snapshot;
if(name.equals(ma.getName())) {
return ma;
}
} else if(snapshot instanceof SplitSnapshot) {
SplitSnapshot split = (SplitSnapshot)snapshot;
for(Iterator it = split.getChildSnapshots().iterator(); it.hasNext(); ) {
ElementSnapshot child = (ElementSnapshot)it.next();
ModeSnapshot ma = findModeSnapshotOfName(child, name);
if(ma != null) {
return ma;
}
}
} else if(snapshot instanceof EditorSnapshot) {
EditorSnapshot editorSnapshot = (EditorSnapshot)snapshot;
ModeSnapshot ma = findModeSnapshotOfName(editorSnapshot.getEditorAreaSnapshot(), name);
if(ma != null) {
return ma;
}
}
return null;
}
/** Superclass for snapshot of model element.
* There are three types, split, mode, and editor (represents editor area) type. */
public static abstract class ElementSnapshot {
// PENDING revise
/** Corresponding object in model (SplitNode or ModeNode or ModeImpl for separate mode). */
private final ModelElement originator;
private /*final*/ SplitSnapshot parent;
public ElementSnapshot(ModelElement originator, SplitSnapshot parent) {
this.originator = originator;
setParent(parent);
}
/** Gets originator object. Used only in model. */
public ModelElement getOriginator() {
return originator;
}
public void setParent(SplitSnapshot parent) {
if(this.parent == null) {
this.parent = parent;
} else {
throw new IllegalStateException("Parent can be set only once," // NOI18N
+ " this.parent=" + this.parent + ", parent=" + parent); // NOI18N
}
}
public SplitSnapshot getParent() {
return parent;
}
public boolean originatorEquals(ElementSnapshot o) {
return getClass().equals(o.getClass()) // To prevent mismatch between split and mode snapshot.
// Split has now originator corresponding to first child.
&& ((ElementSnapshot)o).originator == originator;
}
public abstract double getResizeWeight();
/** Indicates whether component represented by this element is visible or not. */
public abstract boolean isVisibleInSplit();
/** Indicates whether there is at least one visible descendant (split relevant). */
public abstract boolean hasVisibleDescendant();
public String toString() {
return "Snapshot[originatorHash=" + (originator != null ? Integer.toHexString(originator.hashCode()) : "null" ) + "]"; // NOI18N
}
}
/** */
public static class SplitSnapshot extends ElementSnapshot {
private final int orientation;
private final List<ElementSnapshot> childSnapshots = new ArrayList<ElementSnapshot>();
private final Map<ElementSnapshot, Double> childSnapshot2splitWeight = new HashMap<ElementSnapshot, Double>();
private final double resizeWeight;
public SplitSnapshot(ModelElement originator, SplitSnapshot parent, int orientation,
List<ElementSnapshot> childSnapshots,
Map<ElementSnapshot, Double> childSnapshot2splitWeight, double resizeWeight) {
super(originator, parent); // XXX PENDING originator corresponds to the first child model element.
this.orientation = orientation;
this.childSnapshots.addAll(childSnapshots);
this.childSnapshot2splitWeight.putAll(childSnapshot2splitWeight);
this.resizeWeight = resizeWeight;
}
public int getOrientation() {
return orientation;
}
public List getVisibleChildSnapshots() {
List<ElementSnapshot> l = getChildSnapshots();
for(Iterator<ElementSnapshot> it = l.iterator(); it.hasNext(); ) {
ElementSnapshot child = it.next();
if(!child.hasVisibleDescendant()) {
it.remove();
}
}
return l;
}
public List<ElementSnapshot> getChildSnapshots() {
return new ArrayList<ElementSnapshot>(childSnapshots);
}
public double getChildSnapshotSplitWeight(ElementSnapshot childSnapshot) {
Double d = (Double)childSnapshot2splitWeight.get(childSnapshot);
return d == null ? -1 : d.doubleValue();
}
public double getResizeWeight() {
return resizeWeight;
}
/** Indicates whether component represented by this node is visible or not. */
public boolean isVisibleInSplit() {
int count = 0;
for(Iterator it = getChildSnapshots().iterator(); it.hasNext(); ) {
ElementSnapshot child = (ElementSnapshot)it.next();
if(child.hasVisibleDescendant()) {
count++;
// At leas two are needed so the split is showing.
if(count >= 2
//#124847
|| (Constants.SWITCH_HIDE_EMPTY_DOCUMENT_AREA
&& getParent() == null && count==1)) {
return true;
}
}
}
return false;
}
/** Indicates whether there is at least one visible descendant. */
public boolean hasVisibleDescendant() {
for(Iterator it = getChildSnapshots().iterator(); it.hasNext(); ) {
ElementSnapshot child = (ElementSnapshot)it.next();
if(child.hasVisibleDescendant()) {
return true;
}
}
return false;
}
public String toString() {
return super.toString() + "[orientation=" // NOI18N
+ (orientation == Constants.HORIZONTAL ? "horizontal" : "vertical") // NOI18N
+ "]"; // NOI18N
}
}
/** */
public static class ModeSnapshot extends ElementSnapshot {
private final ModeImpl mode;
private final String name;
private final int state;
private final int kind;
private final Rectangle bounds;
private final int frameState;
private final TopComponent selectedTopComponent;
private final TopComponent[] openedTopComponents;
private final double resizeWeight;
public ModeSnapshot(ModelElement originator, SplitSnapshot parent, ModeImpl mode, double resizeWeight) {
super(originator, parent);
this.mode = mode;
this.name = mode.getName();
this.state = mode.getState();
this.kind = mode.getKind();
this.bounds = mode.getBounds();
this.frameState = mode.getFrameState();
this.selectedTopComponent = mode.getSelectedTopComponent();
this.openedTopComponents = mode.getOpenedTopComponents().toArray(new TopComponent[0]);
this.resizeWeight = resizeWeight;
}
public boolean originatorEquals(ElementSnapshot o) {
if(!super.originatorEquals(o)) {
return false;
}
// XXX Even if originators are same, they differ if their states are different.
// Difference -> split vs. separate representations.
ModeSnapshot me = (ModeSnapshot)o;
return getState() == me.getState();
}
public ModeImpl getMode() {
return mode;
}
public String getName() {
return name;
}
public int getState() {
return state;
}
public int getKind() {
return kind;
}
public Rectangle getBounds() {
return bounds;
}
public int getFrameState() {
return frameState;
}
public TopComponent getSelectedTopComponent() {
return selectedTopComponent;
}
public TopComponent[] getOpenedTopComponents() {
return openedTopComponents;
}
public double getResizeWeight() {
return resizeWeight;
}
public boolean isVisibleInSplit() {
if(getOpenedTopComponents().length == 0) {
return false;
}
if(getState() == Constants.MODE_STATE_SEPARATED) {
return false;
}
if(mode.getKind() == Constants.MODE_KIND_EDITOR ) {
WindowManagerImpl wm = WindowManagerImpl.getInstance();
if( null != wm.getEditorMaximizedMode() && wm.getEditorMaximizedMode() != mode )
return false;
}
return true;
}
public boolean isVisibleSeparate() {
if(getOpenedTopComponents().length == 0) {
return false;
}
if(getState() == Constants.MODE_STATE_JOINED) {
return false;
}
return true;
}
public boolean hasVisibleDescendant() {
return isVisibleInSplit();
}
public String toString() {
return super.toString() + "[name=" + mode.getName() + ", permanent=" + mode.isPermanent() // NOI18N
+ ", constraints=" + Arrays.asList(mode.getConstraints()) + "]"; // NOI18N
}
}
public static class SlidingModeSnapshot extends ModeSnapshot {
private final String side;
private final Map<TopComponent,Integer> slideInSizes;
public SlidingModeSnapshot(ModeImpl mode, String side, Map<TopComponent,Integer> slideInSizes) {
super(null, null, mode, 0D);
this.side = side;
this.slideInSizes = slideInSizes;
}
public String getSide () {
return side;
}
public Map<TopComponent,Integer> getSlideInSizes() {
return slideInSizes;
}
} // end of SlidingModeSnapshot
/** */
public static class EditorSnapshot extends ElementSnapshot {
private final ModeStructureSnapshot.ElementSnapshot editorAreaSnapshot;
private final double resizeWeight;
public EditorSnapshot(ModelElement originator, SplitSnapshot parent,
ElementSnapshot editorAreaSnapshot, double resizeWeight) {
super(originator, parent);
this.editorAreaSnapshot = editorAreaSnapshot;
this.resizeWeight = resizeWeight;
}
public double getResizeWeight() {
return resizeWeight;
}
public ElementSnapshot getEditorAreaSnapshot() {
return editorAreaSnapshot;
}
/** Indicates whether component represented by this node is visible or not. */
public boolean isVisibleInSplit() {
if(Constants.SWITCH_HIDE_EMPTY_DOCUMENT_AREA) {
return null != editorAreaSnapshot && editorAreaSnapshot.isVisibleInSplit();
} else {
return true;
}
}
/** Indicates whether there is at least one visible descendant. */
public boolean hasVisibleDescendant() {
return isVisibleInSplit();
}
public String toString() {
return super.toString() + "\n" + editorAreaSnapshot; // NOI18N
}
}
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("\nModesSnapshot hashCode=" + Integer.toHexString(hashCode())); // NOI18N
sb.append("\nSplit modes:\n"); // NOI18N
sb.append(dumpSnapshot(splitRootSnapshot, 0));
sb.append("\nSeparate Modes:"); // NOI18N
sb.append(dumpSet(separateModeSnapshots));
return sb.toString();
}
private static String dumpSnapshot(ElementSnapshot snapshot, int indent) {
StringBuffer sb = new StringBuffer();
String indentString = createIndentString(indent);
if(snapshot instanceof SplitSnapshot) {
SplitSnapshot splitSnapshot = (SplitSnapshot)snapshot;
sb.append(indentString + "split="+splitSnapshot); // NOI18N
indent++;
for(Iterator it = splitSnapshot.getChildSnapshots().iterator(); it.hasNext(); ) {
ElementSnapshot child = (ElementSnapshot)it.next();
sb.append("\n" + dumpSnapshot(child, indent)); // NOI18N
}
} else if(snapshot instanceof ModeSnapshot) {
sb.append(indentString + "mode=" + snapshot); // NOI18N
} else if(snapshot instanceof EditorSnapshot) {
sb.append(indentString + "editor=" + snapshot); // NOI18N
sb.append(dumpSnapshot(((EditorSnapshot)snapshot).getEditorAreaSnapshot(), ++indent));
}
return sb.toString();
}
private static String createIndentString(int indent) {
StringBuffer sb = new StringBuffer(indent);
for(int i = 0; i < indent; i++) {
sb.append(' ');
}
return sb.toString();
}
private static String dumpSet(Set separateModes) {
StringBuffer sb = new StringBuffer();
for(java.util.Iterator it = separateModes.iterator(); it.hasNext(); ) {
sb.append("\nmode=" + it.next());
}
return sb.toString();
}
}