// This file is part of AceWiki.
// Copyright 2008-2013, AceWiki developers.
//
// AceWiki is free software: you can redistribute it and/or modify it under the terms of the GNU
// Lesser General Public License as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// AceWiki is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
// even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License along with AceWiki. If
// not, see http://www.gnu.org/licenses/.
package ch.uzh.ifi.attempto.preditor;
import java.util.List;
import nextapp.echo.app.Alignment;
import nextapp.echo.app.ApplicationInstance;
import nextapp.echo.app.Border;
import nextapp.echo.app.Button;
import nextapp.echo.app.Color;
import nextapp.echo.app.Column;
import nextapp.echo.app.Component;
import nextapp.echo.app.Extent;
import nextapp.echo.app.Font;
import nextapp.echo.app.Insets;
import nextapp.echo.app.Row;
import nextapp.echo.app.TaskQueueHandle;
import nextapp.echo.app.event.ActionEvent;
import nextapp.echo.app.event.ActionListener;
import ch.uzh.ifi.attempto.echocomp.EchoThread;
import ch.uzh.ifi.attempto.echocomp.Style;
import echopoint.ContainerEx;
import echopoint.able.Scrollable;
/**
* This class represents a menu block of the predictive editor. A menu block consists of a list of
* menu items.
*
* @author Tobias Kuhn
*/
class MenuBlock extends Column implements ActionListener {
private static final long serialVersionUID = -5856577034761259001L;
private PreditorWindow preditor;
private MenuBlockContent content;
private ContainerEx container;
private Column menuColumn = new Column();
private Button label = new Button("...");
private Button enlargeButton = new Button();
private int state = 0;
private List<MenuItem> items;
private int width, height;
private int colorShift;
private int progress;
private final ApplicationInstance app;
private final TaskQueueHandle taskQueue;
private final int lazyEvalStep = 25;
/**
* Creates a new menu block.
*
* @param actionListener The action listener.
*/
MenuBlock(int width, int height, int colorShift, PreditorWindow preditor) {
this.width = width;
this.height = height;
this.colorShift = colorShift % 360;
this.app = EchoThread.getActiveApplication();
this.taskQueue = app.createTaskQueue();
this.preditor = preditor;
setInsets(new Insets(0, 1, 0, 0));
Row labelRow = new Row();
label.setEnabled(false);
label.setHeight(new Extent(16));
label.setWidth(new Extent(100));
label.setDisabledBackground(Color.WHITE);
label.setDisabledForeground(Color.BLACK);
label.setDisabledFont(new Font(Style.fontTypeface, Font.ITALIC, new Extent(11)));
label.setRolloverEnabled(false);
label.setLineWrap(false);
label.setAlignment(new Alignment(Alignment.LEFT, Alignment.BOTTOM));
label.setInsets(new Insets(1, 0, 0, 0));
labelRow.add(label);
enlargeButton.setHeight(new Extent(15));
enlargeButton.setWidth(new Extent(10));
enlargeButton.setFont(new Font(Style.fontTypeface, Font.BOLD, new Extent(11)));
enlargeButton.setForeground(Style.lightBackground);
enlargeButton.setRolloverEnabled(true);
enlargeButton.setRolloverForeground(Color.BLACK);
enlargeButton.addActionListener(this);
setEnlarged(false);
labelRow.add(enlargeButton);
add(labelRow);
container = new ContainerEx();
container.setBorder(new Border(1, Color.BLACK, Border.STYLE_INSET));
container.setBackground(shiftColor(Style.lightBackground));
container.setScrollBarPolicy(Scrollable.AUTO);
container.setWidth(new Extent(this.width));
container.setHeight(new Extent(this.height));
add(container);
Column menuBaseColumn = new Column();
menuBaseColumn.setBackground(shiftColor(Style.mediumBackground));
menuBaseColumn.add(menuColumn);
container.add(menuBaseColumn);
}
private Color shiftColor(Color color) {
return Style.shiftColor(color, colorShift);
}
/**
* Sets the content and the size of this menu block.
*
* @param content The content to be shown in this menu block.
*/
public synchronized void setContent(MenuBlockContent content) {
this.content = content;
state++;
label.setText(content.getName());
label.setWidth(new Extent(width - 8));
menuColumn.removeAll();
items = content.getItems();
progress = 0;
if (items.size() > height/15) {
menuColumn.add(createNextMenuComponent());
calculateRest(state);
} else {
for (MenuItem m : items) {
m.setColorShift(colorShift);
menuColumn.add(m);
m.setWidth(new Extent(width - 4));
}
progress = items.size();
}
}
/**
* Returns the current content of this menu block.
*
* @return The content.
*/
public MenuBlockContent getContent() {
return content;
}
/**
* Clears the content and removes all menu items.
*/
public void clear() {
state++;
content = null;
menuColumn.removeAll();
}
private synchronized void calculateRest(final int state) {
if (progress >= items.size()) return;
if (this.state != state) return;
EchoThread thread = new EchoThread() {
public ApplicationInstance getApplication() {
return app;
}
public void run() {
final Component c = createNextMenuComponent();
app.enqueueTask(
taskQueue,
new Runnable() {
public void run() {
addMenuComponent(c, state);
}
}
);
}
};
thread.start();
}
private synchronized void addMenuComponent(Component c, int state) {
if (this.state != state) return;
menuColumn.add(c);
calculateRest(state);
}
private synchronized Component createNextMenuComponent() {
Column c = new Column();
int endPos = progress + lazyEvalStep;
if (endPos > items.size()) endPos = items.size();
for (int i = progress ; i < endPos ; i++) {
MenuItem m = items.get(i);
m.setColorShift(colorShift);
m.setWidth(new Extent(width - 24));
c.add(m);
}
progress = endPos;
return c;
}
public void setVisible(boolean visible) {
state++;
super.setVisible(visible);
}
/**
* This method is used to switch from normal to enlarged mode and back.
*
* @param enlarged true to switch to enlarged mode; false to switch back.
*/
public void setEnlarged(boolean enlarged) {
if (enlarged) {
enlargeButton.setText("–");
enlargeButton.setToolTipText(preditor.getLocalized("preditor_menublocktooltip_normalsize"));
enlargeButton.setActionCommand("downsize");
} else {
enlargeButton.setText("+");
enlargeButton.setToolTipText(preditor.getLocalized("preditor_menublocktooltip_enlarge"));
enlargeButton.setActionCommand("enlarge");
}
}
public void actionPerformed(ActionEvent e) {
String c = e.getActionCommand();
preditor.actionPerformed(new ActionEvent(this, c));
}
}