/*
* Copyright (c) 2014. Matthew Campbell <matthew.campbell@mq.edu.au>, David R. Damerell <david@nixbioinf.org>.
*
* This file is part of GlycanBuilder Vaadin Release and its affliated projects EUROCarbDB, UniCarb-DB and UniCarbKB.
*
* This program is free software free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GlycanBuilder Vaadin Release 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 General Public License (LICENSE.txt) for more details.
*
* You should have received a copy of the GNU General Public License
* along with GlycanBuilder Vaadin Release. If not, see <http ://www.gnu.org/licenses/>.
*/
package ac.uk.icl.dell.vaadin.canvas.basiccanvas;
import java.util.ArrayList;
import java.util.List;
import ac.uk.icl.dell.vaadin.canvas.basiccanvas.font.Font;
import ac.uk.icl.dell.vaadin.canvas.basiccanvas.font.FontCharacter;
import ac.uk.icl.dell.vaadin.canvas.basiccanvas.font.FontPoint;
import ac.uk.icl.dell.vaadin.canvas.basiccanvas.font.FontSegment;
import ac.uk.icl.dell.vaadin.canvas.hezamu.canvas.Canvas;
import ac.uk.icl.dell.vaadin.canvas.hezamu.canvas.Canvas.CanvasMouseDownListener;
import ac.uk.icl.dell.vaadin.canvas.hezamu.canvas.Canvas.CanvasMouseUpListener;
public class BasicCanvas extends Canvas implements CanvasMouseDownListener, CanvasMouseUpListener {
private static final long serialVersionUID = 1777004722553284089L;
public Font font;
public boolean italics=false;
private int mouseDownXValue = 0;
private int mouseDownYValue = 0;
private List<SelectionListener> selectionListeners;
public boolean awaitingInstructions=false;
public BasicCanvas(){
this.addListener((CanvasMouseUpListener)this);
this.addListener((CanvasMouseDownListener)this);
selectionListeners=new ArrayList<SelectionListener>();
}
public interface SelectionListener{
public void recieveSelectionUpdate(double x, double y, double width, double height,boolean mouseMoved);
}
/**
*
* @param character
* @param x
* @param y
* @return
*/
public double renderChar(char character,double x, double y){
FontCharacter fontCharacter=font.get(character);
for(FontSegment fontSegment:fontCharacter){
boolean first=true;
for(FontPoint fontPoint:fontSegment){
if(first){
this.moveTo(x + fontPoint.getX(italics), y + fontPoint.getY());
first = false;
}else{
this.lineTo(x + fontPoint.getX(italics), y + fontPoint.getY());
}
}
}
return fontCharacter.getWidth();
}
/**
* Text to be drawn on the canvas at position x,y with a rotation of angle radian and scaled
* @param text text to be drawn
* @param x position
* @param y position
* @param angle in radian (put 0 to draw text horizontally)
* @param scale (put 1 for character 12 pixels high)
* @return the width (in pixels) of the text
*/
public double renderText(String text, double x, double y, double angle, double scale) {
super.translate(x, y);
super.rotate(angle);
super.scale(scale, scale);
double rc = 0.0;
for (int i = 0; i < text.length(); i++) {
rc += renderChar(text.charAt(i), rc, 0.0);
}
return rc * scale;
}
/**
* Calculate text width
* @param text
* @param scale
* @return
*/
public double calculateTextWidth(String text,double scale){
double rc=0.0;
for(int i=0;i<text.length();i++) {
rc+=font.get(text.charAt(i)).getWidth();
}
return rc*scale;
}
public Font getFont() {
return font;
}
public void setFont(Font font) {
this.font = font;
}
public boolean isItalics() {
return italics;
}
public void setItalics(boolean italics) {
this.italics = italics;
}
public void renderAllFontSymbols(double x, double y,double maximumWidth){
for(FontCharacter fontCharacter:font.orderedFontList){
this.saveContext();
this.beginPath();
setStrokeStyle(0,0,0);
for(FontSegment fontSegment : fontCharacter){
boolean first = true;
for(FontPoint fontPoint : fontSegment){
if(first){
this.moveTo(x + fontPoint.getX(false), y + fontPoint.getY());
first = false;
}else{
this.lineTo(x + fontPoint.getX(false), y + fontPoint.getY());
}
}
}
this.stroke();
this.restoreContext();
double width=fontCharacter.getWidth();
x+=width;
if(x>=maximumWidth){
x=0;
y+=font.characterSetMaxHeight;
}
}
}
/**
*
* @param startingScale
* @param decrementFactor
* @param maxWidth
* @param maxHeight
* @param text
* @return
* @TODO Add support for scaling up, split in list of methods
*/
public TextInfo getRequiredScale(double startingScale, double decrementFactor, double maxWidth, double maxHeight,String text){
double scale=startingScale;
double width;
while(true){
width=calculateTextWidth(text, scale);
if(scale<decrementFactor){
width=calculateTextWidth(text, decrementFactor);
scale=decrementFactor;
}else if(width>maxWidth){
scale-=decrementFactor;
}else{
break;
}
}
double height;
while(true){
height=calculateTextWidth(text, scale);
if(scale<decrementFactor){
height=calculateTextWidth(text, decrementFactor);
scale=decrementFactor;
}else if(height>maxHeight){
scale-=decrementFactor;
}else{
break;
}
}
return new TextInfo(scale,width,height);
}
public class TextInfo{
public double scale;
public double height;
public double width;
public TextInfo(double _scale, double _width, double _height){
scale=_scale;
width=_width;
height=_height;
}
}
@Override
public void mouseDown(int x, int y) {
mouseDownXValue = x;
mouseDownYValue = y;
System.err.println("Mouse down event!");
for(SelectionListener listener:selectionListeners){
listener.recieveSelectionUpdate(x, y, 0, 0, false);
}
}
@Override
public void mouseUp(int x, int y) {
if (mouseDownXValue != x || mouseDownYValue != y)
{
notifySelectionListeners(mouseDownXValue < x ? mouseDownXValue : x, mouseDownYValue < y ? mouseDownYValue : y,
Math.abs(mouseDownXValue - x), Math.abs(mouseDownYValue - y), true);
}
super.moveTo(x, y);
}
public void notifySelectionListeners(double x, double y, double width, double height,boolean dragged){
for(SelectionListener listener:selectionListeners){
listener.recieveSelectionUpdate(x, y, width, height,dragged);
}
}
public void addSelectionListener(SelectionListener listener){
selectionListeners.add(listener);
}
}