blob: eff454afb89ea69ef97728042625b699c33abda2 [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.view.View;
import org.netbeans.core.windows.view.ViewEvent;
import org.netbeans.core.windows.view.ViewFactory;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.netbeans.core.windows.view.dnd.TopComponentDraggable;
import org.openide.windows.TopComponent;
/**
* Class responsible for communication between central and view parts.
* It sends requests to view. Also provides coallescing of more
* requests and is also responsible for scheduling the requests into AWT thread.
* This class is thread safe.
*
* @author Peter Zavadsky
*/
class ViewRequestor {
/** Associated central. */
private final Central central;
/** View of window system. */
private final View view;
/** List of requests to process. */
private final List<ViewRequest> requests = new ArrayList<ViewRequest>(10);
// PENDING
/** Instance of snapshot which is passed to view. Reflects the actual state of model.
* Manipulate it in AWT thread only. */
private WindowSystemSnapshot snapshot;
private boolean reentryFlag = false;
/** Debugging flag. */
private static final boolean DEBUG = Debug.isLoggable(ViewRequestor.class);
/** Creates a new instance of ViewRequestor */
public ViewRequestor(Central central) {
this.central = central;
this.view = ViewFactory.createWindowSystemView(central);
}
// XXX PENDING Method requesting state of view... do not mix with the rest.
// It shoudn't exist any link in direction view -> central.
public boolean isDragInProgress() {
return view.isDragInProgress();
}
// XXX PENDING Method requesting info of view... do not mix with the rest.
// It shouldn't exist any link in directtion view -> central, but due to old API.
public Frame getMainWindow() {
return view.getMainWindow();
}
public Component getEditorAreaComponent() {
return view.getEditorAreaComponent();
}
public String guessSlideSide(TopComponent tc) {
return view.guessSlideSide(tc);
}
/** Schedules request into AWT. */
public void scheduleRequest(ViewRequest request) {
if(request.type == View.CHANGE_VISIBILITY_CHANGED) {
// Most important request, takes precedence to all others.
postVisibilityRequest(request);
return;
}
coallesceRequest(request);
postRequest();
}
/** Coallesce request. */
private void coallesceRequest(ViewRequest request) {
Object source = request.source;
int type = request.type;
boolean doCoallesce =
type == View.CHANGE_ACTIVE_MODE_CHANGED
|| type == View.CHANGE_EDITOR_AREA_BOUNDS_CHANGED
|| type == View.CHANGE_EDITOR_AREA_CONSTRAINTS_CHANGED
|| type == View.CHANGE_EDITOR_AREA_STATE_CHANGED
|| type == View.CHANGE_EDITOR_AREA_FRAME_STATE_CHANGED
|| type == View.CHANGE_MAIN_WINDOW_BOUNDS_JOINED_CHANGED
|| type == View.CHANGE_MAIN_WINDOW_BOUNDS_SEPARATED_CHANGED
|| type == View.CHANGE_MAIN_WINDOW_FRAME_STATE_JOINED_CHANGED
|| type == View.CHANGE_MAIN_WINDOW_FRAME_STATE_SEPARATED_CHANGED
|| type == View.CHANGE_MAXIMIZED_MODE_CHANGED
|| type == View.CHANGE_MODE_SELECTED_TOPCOMPONENT_CHANGED
|| type == View.CHANGE_MODE_BOUNDS_CHANGED
|| type == View.CHANGE_MODE_CONSTRAINTS_CHANGED
|| type == View.CHANGE_MODE_FRAME_STATE_CHANGED
|| type == View.CHANGE_TOOLBAR_CONFIGURATION_CHANGED
|| type == View.CHANGE_TOPCOMPONENT_ICON_CHANGED
|| type == View.CHANGE_TOPCOMPONENT_DISPLAY_NAME_CHANGED
|| type == View.CHANGE_TOPCOMPONENT_DISPLAY_NAME_ANNOTATION_CHANGED
|| type == View.CHANGE_TOPCOMPONENT_TOOLTIP_CHANGED
|| type == View.CHANGE_TOPCOMPONENT_ACTIVATED
|| type == View.CHANGE_DND_PERFORMED
|| type == View.CHANGE_UI_UPDATE
|| type == View.TOPCOMPONENT_CANCEL_REQUEST_ATTENTION
|| type == View.TOPCOMPONENT_REQUEST_ATTENTION
|| type == View.TOPCOMPONENT_ATTENTION_HIGHLIGHT_OFF
|| type == View.TOPCOMPONENT_ATTENTION_HIGHLIGHT_ON;
synchronized(requests) {
Object oldValue = null;
if(doCoallesce) {
for(Iterator it = requests.iterator(); it.hasNext(); ) {
ViewRequest r = (ViewRequest)it.next();
if(source == r.source && type == r.type) {
// Remove the old request (it will be replaced by new one).
it.remove();
oldValue = r.oldValue;
break;
}
}
}
if(oldValue != null) {
// Actually coallesce.
requests.add(new ViewRequest(
request.source, request.type, oldValue, request.newValue));
} else {
requests.add(request);
}
}
}
private void postRequest() {
if(SwingUtilities.isEventDispatchThread()) {
processRequest();
} else {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
processRequest();
}
});
}
}
private void postVisibilityRequest(final ViewRequest visibilityRequest) {
if(SwingUtilities.isEventDispatchThread()) {
processVisibilityRequest(visibilityRequest);
} else {
final long time = System.currentTimeMillis();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
if(DEBUG) {
debugLog("Rescheduling request into AWT took=" // NOI18N
+ (System.currentTimeMillis() - time) + " ms"); // NOI18N
}
processVisibilityRequest(visibilityRequest);
}
});
}
}
///////////////////////////////////////////
// !! AWT thread only >>
private void processRequest() {
if (reentryFlag) {
return;
}
if(snapshot == null) {
// The system was made invisible.
return;
}
ViewRequest[] rs;
synchronized(requests) {
if(requests.isEmpty()) {
// No requests left.
return;
}
rs = requests.toArray(new ViewRequest[0]);
requests.clear();
}
List<ViewEvent> viewEvents = new ArrayList<ViewEvent>();
updateSnapshot(rs);
for(int i = 0; i < rs.length; i++) {
ViewRequest r = rs[i];
if (DEBUG) {
debugLog("Creating a view event for " + r);
}
viewEvents.add(getViewEvent(r));
}
dispatchRequest(viewEvents.toArray(new ViewEvent[0]), snapshot);
}
private void processVisibilityRequest(ViewRequest visibilityRequest) {
if(((Boolean)visibilityRequest.newValue).booleanValue()) {
// Is visible, set snapshot
snapshot = central.createWindowSystemSnapshot();
} else {
// Is invisible, clear it.
snapshot = null;
}
dispatchRequest(new ViewEvent[] { new ViewEvent(
visibilityRequest.source,
visibilityRequest.type,
visibilityRequest.oldValue,
visibilityRequest.newValue)},
snapshot);
}
private void dispatchRequest(ViewEvent[] viewEvents, WindowSystemSnapshot snapshot) {
try {
reentryFlag = true;
view.changeGUI(viewEvents, snapshot);
} finally {
reentryFlag = false;
// check for events that appeared while processing..
processRequest();
}
}
private void updateSnapshot(ViewRequest[] requests) {
// PENDING Possibly optimization, update to snapshot only changed values
// ans create new structure snapshot only in case it affect strucure update.
long time = System.currentTimeMillis();
WindowSystemSnapshot currentSnapshot = central.createWindowSystemSnapshot();
snapshot.setMainWindowBoundsJoined(currentSnapshot.getMainWindowBoundsJoined());
snapshot.setMainWindowBoundsSeparated(currentSnapshot.getMainWindowBoundsSeparated());
snapshot.setMainWindowFrameStateJoined(currentSnapshot.getMainWindowFrameStateJoined());
snapshot.setMainWindowFrameStateSeparated(currentSnapshot.getMainWindowFrameStateSeparated());
snapshot.setEditorAreaState(currentSnapshot.getEditorAreaState());
snapshot.setEditorAreaFrameState(currentSnapshot.getEditorAreaFrameState());
snapshot.setEditorAreaBounds(currentSnapshot.getEditorAreaBounds());
snapshot.setActiveModeSnapshot(currentSnapshot.getActiveModeSnapshot());
snapshot.setMaximizedModeSnapshot(currentSnapshot.getMaximizedModeSnapshot());
snapshot.setModeStructureSnapshot(currentSnapshot.getModeStructureSnapshot());
snapshot.setToolbarConfigurationName(currentSnapshot.getToolbarConfigurationName());
snapshot.setProjectName(currentSnapshot.getProjectName());
if(DEBUG) {
debugLog("Updating winsys snapshot took=" // NOI18N
+ (System.currentTimeMillis() - time) + " ms"); // NOI18N
debugLog(snapshot.toString());
}
}
// XXX PENDING Adjusts the source event to the view needs.
private ViewEvent getViewEvent(ViewRequest request) {
Object source = request.source;
int type = request.type;
Object oldValue = request.oldValue;
Object newValue = request.newValue;
/*if(type == View.CHANGE_ACTIVE_MODE_CHANGED) {
} else if(type == View.CHANGE_MAXIMIZED_MODE_CHANGED) {
} else if(type == View.CHANGE_EDITOR_AREA_BOUNDS_CHANGED) {
} else if(type == View.CHANGE_EDITOR_AREA_STATE_CHANGED) {
} else if(type == View.CHANGE_EDITOR_AREA_FRAME_STATE_CHANGED) {
} else if(type == View.CHANGE_MAIN_WINDOW_BOUNDS_JOINED_CHANGED) {
} else if(type == View.CHANGE_MAIN_WINDOW_BOUNDS_SEPARATED_CHANGED) {
} else if(type == View.CHANGE_MAIN_WINDOW_FRAME_STATE_JOINED_CHANGED) {
} else if(type == View.CHANGE_MAIN_WINDOW_FRAME_STATE_SEPARATED_CHANGED) {
} else if(type == View.CHANGE_TOOLBAR_CONFIGURATION_CHANGED) {
} else if(type == View.CHANGE_MODE_ADDED) {
} else if(type == View.CHANGE_MODE_REMOVED) {
} else if(type == View.CHANGE_SPLITS_CHANGED) {
} else*/ if(type == View.CHANGE_MODE_SELECTED_TOPCOMPONENT_CHANGED) {
return new ViewEvent(((ModeImpl)source).getName(), type, oldValue, newValue);
// } else if(type == View.CHANGE_MODE_CONSTRAINTS_CHANGED) {
} else if(type == View.CHANGE_MODE_TOPCOMPONENT_ADDED) {
return new ViewEvent(((ModeImpl)source).getName(), type, oldValue, newValue);
} else if(type == View.CHANGE_MODE_TOPCOMPONENT_REMOVED) {
return new ViewEvent(((ModeImpl)source).getName(), type, oldValue, newValue);
} else if(type == View.CHANGE_MODE_BOUNDS_CHANGED) {
return new ViewEvent(((ModeImpl)source).getName(), type, oldValue, newValue);
} else if(type == View.CHANGE_MODE_FRAME_STATE_CHANGED) {
return new ViewEvent(((ModeImpl)source).getName(), type, oldValue, newValue);
} else if(type == View.CHANGE_TOPCOMPONENT_ICON_CHANGED) {
return new ViewEvent(((ModeImpl)source).getName(), type, oldValue, newValue);
} else if(type == View.CHANGE_TOPCOMPONENT_DISPLAY_NAME_CHANGED) {
return new ViewEvent(((ModeImpl)source).getName(), type, oldValue, newValue);
} else if(type == View.CHANGE_TOPCOMPONENT_DISPLAY_NAME_ANNOTATION_CHANGED) {
return new ViewEvent(((ModeImpl)source).getName(), type, oldValue, newValue);
} else if(type == View.CHANGE_TOPCOMPONENT_TOOLTIP_CHANGED) {
return new ViewEvent(((ModeImpl)source).getName(), type, oldValue, newValue);
} else if(type == View.CHANGE_TOPCOMPONENT_ACTIVATED) {
return new ViewEvent(((ModeImpl)source).getName(), type, oldValue, newValue);
} else if(type == View.CHANGE_MODE_CLOSED) {
return new ViewEvent(((ModeImpl)source).getName(), type, oldValue, newValue);
}
return new ViewEvent(source, type, oldValue, newValue);
}
// !! AWT thread only <<
///////////////////////////////////////////
private static void debugLog(String message) {
Debug.log(ViewRequestor.class, message);
}
void userStartedKeyboardDragAndDrop( TopComponentDraggable draggable ) {
view.userStartedKeyboardDragAndDrop( draggable );
}
}