blob: fb1a96fdfc3789b059a21cb497e9f3aef5c1d6de [file] [log] [blame]
//Copyright (C) 2013 The Android Open Source Project
//
// 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.gerrit.client.diff;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Label;
import net.codemirror.lib.CodeMirror;
import net.codemirror.lib.LineCharacter;
import java.util.ArrayList;
import java.util.List;
/** The Widget that handles the scrollbar gutters */
class SidePanel extends Composite {
interface Binder extends UiBinder<HTMLPanel, SidePanel> {}
private static final Binder uiBinder = GWT.create(Binder.class);
interface SidePanelStyle extends CssResource {
String gutter();
String halfGutter();
String comment();
String draft();
String insert();
String delete();
}
enum GutterType {
COMMENT, DRAFT, INSERT, DELETE, EDIT;
}
@UiField
SidePanelStyle style;
private List<GutterWrapper> gutters;
private CodeMirror cmB;
SidePanel() {
initWidget(uiBinder.createAndBindUi(this));
this.gutters = new ArrayList<GutterWrapper>();
}
GutterWrapper addGutter(CodeMirror cm, int line, GutterType type) {
Label gutter = new Label();
GutterWrapper info = new GutterWrapper(this, gutter, cm, line, type);
adjustGutter(info);
gutter.addStyleName(style.gutter());
switch (type) {
case COMMENT:
gutter.addStyleName(style.comment());
break;
case DRAFT:
gutter.addStyleName(style.draft());
gutter.setText("*");
break;
case INSERT:
gutter.addStyleName(style.insert());
break;
case DELETE:
gutter.addStyleName(style.delete());
break;
case EDIT:
gutter.addStyleName(style.insert());
Label labelLeft = new Label();
labelLeft.addStyleName(style.halfGutter());
gutter.getElement().appendChild(labelLeft.getElement());
}
((HTMLPanel) getWidget()).add(gutter);
gutters.add(info);
return info;
}
void adjustGutters(CodeMirror cmB) {
this.cmB = cmB;
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
@Override
public void execute() {
for (GutterWrapper info : gutters) {
adjustGutter(info);
}
}
});
}
private void adjustGutter(GutterWrapper wrapper) {
if (cmB == null) {
return;
}
final CodeMirror cm = wrapper.cm;
final int line = wrapper.line;
Label gutter = wrapper.gutter;
final double height = cm.heightAtLine(line, "local");
final double scrollbarHeight = cmB.getScrollbarV().getClientHeight();
double top = height / (double) cmB.getSizer().getClientHeight() *
scrollbarHeight +
cmB.getScrollbarV().getAbsoluteTop();
if (top == 0) {
top = -10;
}
gutter.getElement().getStyle().setTop(top, Unit.PX);
wrapper.replaceClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
cm.setCursor(LineCharacter.create(line));
cm.scrollToY(Math.max(0, height - 0.5 * scrollbarHeight));
cm.focus();
}
});
}
void removeGutter(GutterWrapper wrapper) {
gutters.remove(wrapper);
}
static class GutterWrapper {
private SidePanel host;
private Label gutter;
private CodeMirror cm;
private int line;
private HandlerRegistration regClick;
GutterWrapper(SidePanel host, Label anchor, CodeMirror cm, int line,
GutterType type) {
this.host = host;
this.gutter = anchor;
this.cm = cm;
this.line = line;
}
private void replaceClickHandler(ClickHandler newHandler) {
if (regClick != null) {
regClick.removeHandler();
}
regClick = gutter.addClickHandler(newHandler);
}
void remove() {
gutter.removeFromParent();
host.removeGutter(this);
}
}
}