// Copyright 2012 Google Inc. All Rights Reserved. // // Licensed 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 com.google.collide.client.editor.selection; import com.google.collide.client.AppContext; import com.google.collide.client.editor.Buffer; import com.google.collide.client.editor.Editor; import com.google.collide.client.editor.FocusManager; import com.google.collide.client.editor.Editor.ReadOnlyListener; import com.google.collide.json.shared.JsonArray; import com.google.collide.shared.document.LineInfo; import com.google.collide.shared.util.JsonCollections; import com.google.collide.shared.util.ListenerRegistrar; /** * A controller responsible for keeping the local user's cursor renderer * up-to-date. * */ public class LocalCursorController implements SelectionModel.CursorListener, FocusManager.FocusListener, ReadOnlyListener { public static LocalCursorController create(AppContext appContext, FocusManager focusManager, SelectionModel selectionModel, Buffer buffer, Editor editor) { CursorView cursorView = CursorView.create(appContext, true); return new LocalCursorController(focusManager, selectionModel, cursorView, buffer, editor); } private final Buffer buffer; private final CursorView cursorView; private final JsonArray<ListenerRegistrar.Remover> listenerRemovers = JsonCollections.createArray(); private final SelectionModel selectionModel; private LocalCursorController(FocusManager focusManager, SelectionModel selectionModel, CursorView cursorView, Buffer buffer, Editor editor) { this.selectionModel = selectionModel; this.cursorView = cursorView; this.buffer = buffer; resetCursorView(); listenerRemovers.add(focusManager.getFocusListenerRegistrar().add(this)); listenerRemovers.add(selectionModel.getCursorListenerRegistrar().add(this)); listenerRemovers.add(editor.getReadOnlyListenerRegistrar().add(this)); attachCursorElement(); onFocusChange(focusManager.hasFocus()); onReadOnlyChanged(editor.isReadOnly()); } private void attachCursorElement() { buffer.addAnchoredElement(selectionModel.getCursorAnchor(), cursorView.getView().getElement()); } private void detachCursorElement() { buffer.removeAnchoredElement(selectionModel.getCursorAnchor(), cursorView.getView() .getElement()); } @Override public void onCursorChange(LineInfo lineInfo, int column, boolean isExplicitChange) { cursorView.forceSolidBlinkState(); } @Override public void onFocusChange(boolean hasFocus) { cursorView.setVisibility(hasFocus); } @Override public void onReadOnlyChanged(boolean isReadOnly) { if (isReadOnly) { detachCursorElement(); } else { attachCursorElement(); } } public void resetCursorView() { cursorView.setColor("black"); cursorView.setBlockMode(false); } /** * TODO: let block mode use and set the color of the * character beneath it to create an inverted color effect. */ public void setBlockMode(boolean enabled) { cursorView.setBlockMode(enabled); } public void setColor(String color) { cursorView.setColor(color); } public void teardown() { for (int i = 0, n = listenerRemovers.size(); i < n; i++) { listenerRemovers.get(i).remove(); } detachCursorElement(); } }