| /* |
| * 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 ); |
| } |
| |
| } |
| |