Java tutorial
// This file is part of Moodle - http://moodle.org/ // // Moodle is 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. // // Moodle 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 for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * @package eMarking * @copyright 2013 Jorge Villaln <villalon@gmail.com> * Hans C. Jeria <hansj@live.cl> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ package cl.uai.client.page; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.logging.Logger; import org.vaadin.gwtgraphics.client.DrawingArea; import cl.uai.client.EMarkingComposite; import cl.uai.client.EMarkingConfiguration; import cl.uai.client.EMarkingWeb; import cl.uai.client.data.Criterion; import cl.uai.client.marks.CheckMark; import cl.uai.client.marks.CommentMark; import cl.uai.client.marks.CrossMark; import cl.uai.client.marks.CustomMark; import cl.uai.client.marks.HighlightMark; import cl.uai.client.marks.Mark; import cl.uai.client.marks.PathMark; import cl.uai.client.marks.Point; import cl.uai.client.marks.QuestionMark; import cl.uai.client.marks.RubricMark; import cl.uai.client.resources.Resources; import cl.uai.client.toolbar.buttons.ButtonFormat; import cl.uai.client.toolbar.buttons.EmarkingToggleButton; import cl.uai.client.toolbar.buttons.MarkingButtons; import com.allen_sauer.gwt.dnd.client.PickupDragController; import com.google.gwt.canvas.client.Canvas; import com.google.gwt.event.dom.client.ContextMenuEvent; import com.google.gwt.event.dom.client.ContextMenuHandler; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.AbsolutePanel; import com.google.gwt.user.client.ui.FocusPanel; import com.google.gwt.user.client.ui.Image; import com.google.gwt.user.client.ui.PopupPanel; import com.google.gwt.user.client.ui.ScrollPanel; /** * @author Jorge Villalon <villalon@gmail.com> * */ public class MarkingPage extends EMarkingComposite implements ContextMenuHandler { public int getWidth() { return width; } public int getHeight() { return height; } /** For loggin purposes **/ Logger logger = Logger.getLogger(MarkingPage.class.getName()); private FocusPanel mainPanel = null; private AbsolutePanel absolutePanel = null; private Canvas canvas = null; private DrawingArea drawingArea = null; /** Drag and Drop controller **/ private PickupDragController dragController = null; private DrawController drawController = null; private MarkingPageDropController dropController = null; /** Page image and number within submission **/ private Image pageImage = null; private int pageNumber = -1; public int getPageNumber() { return pageNumber; } private int width; private int height; /** All marks in this page **/ private Map<Integer, Mark> marks = null; /** * */ public MarkingPage(int pagenum, String image, int width, int height, List<Map<String, String>> pageMarks) { this.pageNumber = pagenum; this.pageImage = new Image(image); this.width = width; this.height = height; this.pageImage.setWidth(this.width + "px"); this.pageImage.setHeight(this.height + "px"); logger.fine("Adding page " + pagenum + " Url:" + image); this.marks = new HashMap<Integer, Mark>(); for (Map<String, String> markMap : pageMarks) { try { int index = Integer.parseInt(markMap.get("format")); ButtonFormat format = index < 1000 ? MarkingButtons.getButtonFormatFromCode(index) : ButtonFormat.BUTTON_CUSTOM; fixPositions(markMap, width, height); Mark mark = null; switch (format) { case BUTTON_COMMENT: mark = CommentMark.createFromMap(markMap); break; case BUTTON_RUBRIC: mark = RubricMark.createFromMap(markMap); break; case BUTTON_TICK: mark = CheckMark.createFromMap(markMap); break; case BUTTON_CROSS: mark = CrossMark.createFromMap(markMap); break; case BUTTON_PEN: mark = PathMark.createFromMap(markMap); break; case BUTTON_HIGHLIGHT: mark = HighlightMark.createFromMap(markMap); break; case BUTTON_QUESTION: mark = QuestionMark.createFromMap(markMap); break; case BUTTON_CUSTOM: mark = CustomMark.createFromMap(markMap); break; default: logger.severe("Invalid format for comment"); mark = null; break; } if (mark != null) { this.marks.put(mark.getId(), mark); } } catch (Exception e) { e.printStackTrace(); logger.severe( "Exception creating mark from DB. " + markMap.toString() + " Error:" + e.getMessage()); } } mainPanel = new FocusPanel(); absolutePanel = new AbsolutePanel(); absolutePanel.addStyleName(Resources.INSTANCE.css().absolutepage()); drawingArea = new DrawingArea(width, height); mainPanel.addClickHandler(new MarkingPageClickHandler(this)); dropController = new MarkingPageDropController(absolutePanel, this); EMarkingWeb.markingInterface.getDragController().registerDropController(dropController); // Initialize drag and drop controller, attached to the absolute panel dragController = new PickupDragController(absolutePanel, true); dragController.setBehaviorDragStartSensitivity(1); dragController.setBehaviorScrollIntoView(false); MarkingPageDragHandler dragHandler = new MarkingPageDragHandler(absolutePanel, this); dragController.addDragHandler(dragHandler); //Initialize Drawing controller for pen tool drawController = new DrawController(); //The draw controller listens to the drawing area drawController.listenTo(mainPanel); //The drag handler listens to the draw controller MarkingPageDrawHandler drawHandler = new MarkingPageDrawHandler(absolutePanel, drawingArea, this); drawController.addListener(drawHandler); MarkingPageHighlightHandler highlightHandler = new MarkingPageHighlightHandler(absolutePanel, drawingArea, this); drawController.addListener(highlightHandler); absolutePanel.add(drawingArea, 0, 0); absolutePanel.add(pageImage); canvas = Canvas.createIfSupported(); if (canvas != null) { canvas.setSize(width + "px", height + "px"); canvas.setCoordinateSpaceWidth(width); canvas.setCoordinateSpaceHeight(height); canvas.addStyleName(Resources.INSTANCE.css().pagecanvas()); absolutePanel.add(canvas, 0, 0); } mainPanel.add(absolutePanel); this.initWidget(mainPanel); addDomHandler(this, ContextMenuEvent.getType()); } /** * Fixes positions coming from Moodle in a 0-1 format to the actual page size * @param map * @param width * @param height */ private void fixPositions(Map<String, String> map, int width, int height) { float originalx = Float.parseFloat(map.get("posx")); float originaly = Float.parseFloat(map.get("posy")); int posx = (int) Math.round(originalx * (float) width); int posy = (int) Math.round(originaly * (float) height); map.remove("posx"); map.remove("posy"); map.put("posx", Integer.toString(posx)); map.put("posy", Integer.toString(posy)); map.put("originalx", Float.toString(originalx)); map.put("originaly", Float.toString(originaly)); try { String pathData = map.get("path"); float originalwidth = Float.parseFloat(map.get("width")); float originalheight = Float.parseFloat(map.get("height")); int endx = Integer.parseInt(pathData.split(",")[0]); int endy = Integer.parseInt(pathData.split(",")[1]); endx = (int) ((float) endx / (float) originalwidth * (float) width); endy = (int) ((float) endy / (float) originalheight * (float) height); map.remove("path"); map.put("path", endx + "," + endy); } catch (Exception e) { } } /** * Gets statistics of each mark type in the page * * @return a hash map with mark id, total appearances pairs */ public Map<Integer, Integer> getMarkStatistics() { Map<Integer, Integer> stats = new HashMap<Integer, Integer>(); List<EmarkingToggleButton> buttons = EMarkingWeb.markingInterface.getToolbar().getMarkingButtons() .getButtons(); for (EmarkingToggleButton btn : buttons) { stats.put(btn.getFormat(), 0); } if (this.marks == null) return stats; for (int markId : this.marks.keySet()) { Mark mark = this.marks.get(markId); int format = mark.getFormat(); if (format >= 1000) { String label = mark.getRawtext(); Integer idx = EMarkingWeb.markingInterface.getToolbar().getMarkingButtons().getCustomButtonIndex() .get(label); if (idx == null) { logger.severe("Custom mark " + label + " index not found"); continue; } else { format = idx; } } if (!stats.containsKey(format)) continue; int newvalue = stats.get(format); stats.remove(format); Criterion selectedCriterion = EMarkingWeb.markingInterface.getToolbar().getMarkingButtons() .getSelectedCriterion(); if (selectedCriterion == null) { newvalue++; } else if (mark.getCriterionId() == selectedCriterion.getId()) { newvalue++; } stats.put(format, newvalue); } return stats; } // Returns the absolute panel for coordinates calculation when dropping new mark public AbsolutePanel getAbsolutePanel() { return absolutePanel; } @Override protected void onLoad() { super.onLoad(); // Once loaded, we know all sizes int i = (int) (Window.getClientWidth()); String strWidth = String.valueOf(i); mainPanel.setWidth(strWidth); mainPanel.addStyleName(Resources.INSTANCE.css().pagescroll()); loadInterface(); } public void loadInterface() { for (Mark mark : this.marks.values()) { addMarkWidget(mark); } } /** * The marks in this page * * @return hashmap with marks (mark id as key) */ public Map<Integer, Mark> getMarkWidgets() { return marks; } /** * Adds a mark to this page * * @param mark Mark object * @return same Mark object */ public Mark addMarkWidget(final Mark mark) { // Adds Mark to hashmap marks.put(mark.getId(), mark); // Make the mark draggable within page if not in readonly mode if (!(mark instanceof PathMark)) { dragController.makeDraggable(mark); } absolutePanel.add(mark, mark.getPosx(), mark.getPosy()); if (mark instanceof RubricMark && EMarkingConfiguration.getMarkingType() == EMarkingConfiguration.EMARKING_TYPE_MARKER_TRAINING) { ((RubricMark) mark).addCollaborativesButtons(); } return mark; } /** * Removes a Mark object from this page by its id * @param id mark id number */ public void deleteMarkWidget(int id) { // Checks if the mark exists within the page Mark mark = marks.get(id); // If exists remove from panel and from hashmap if (mark != null) { if (mark instanceof RubricMark && EMarkingConfiguration .getMarkingType() == EMarkingConfiguration.EMARKING_TYPE_MARKER_TRAINING) { ((RubricMark) mark).removeCollaborativeButtons(); } absolutePanel.remove(mark); marks.remove(id); } } /** * Highlight a particular mark within the page * * @param markId the mark's id */ public void highlightRubricMark(int markId) { if (!(marks.get(markId) instanceof RubricMark)) { return; } RubricMark mark = (RubricMark) marks.get(markId); ScrollPanel scrollPanel = EMarkingWeb.markingInterface.getMarkingPagesInterface().getScrollPanel(); int top = scrollPanel.getVerticalScrollPosition() + (mark.getAbsoluteTop() - scrollPanel.getAbsoluteTop()); scrollPanel.setVerticalScrollPosition(top); } public RubricMark getMarkByLevelId(int lvlid) { RubricMark mark = null; for (Mark m : marks.values()) { if (m instanceof RubricMark) { RubricMark rmark = (RubricMark) m; if (rmark.getLevelId() == lvlid) return rmark; } } return mark; } /** + * Count how many rubric marks has the page. + * @return allMarksInPage + */ public int isHaveRubricMark() { int allMarksInPage = 0; for (Mark m : marks.values()) { if (m instanceof RubricMark) { allMarksInPage++; } } return allMarksInPage; } @Override public void onContextMenu(ContextMenuEvent event) { if (EMarkingConfiguration.isReadonly()) { return; } else { logger.fine("Emarking is not read only so I can show the menu"); } event.getNativeEvent().stopPropagation(); event.getNativeEvent().preventDefault(); int posx = event.getNativeEvent().getClientX(); int posy = event.getNativeEvent().getClientY(); PopupPanel menu = new MarkingMenu(this, posx, posy); menu.show(); } public void resizePage(double centerWidth) { float ratio = (float) this.width / (float) centerWidth; int newwidth = (int) centerWidth; int newheight = Math.round((float) this.height / ratio); for (Mark mark : marks.values()) { Point newPoint = resize(mark.getPosx(), mark.getPosy(), newwidth, newheight); mark.setPosx(newPoint.getX()); mark.setPosy(newPoint.getY()); if (mark instanceof HighlightMark) { HighlightMark hmark = (HighlightMark) mark; newPoint = resize(hmark.getEnd().getX(), hmark.getEnd().getY(), newwidth, newheight); hmark.setEnd(newPoint); hmark.setMarkHTML(); } absolutePanel.setWidgetPosition(mark, mark.getPosx(), mark.getPosy()); } this.width = newwidth; this.height = newheight; this.pageImage.setWidth(this.width + "px"); this.pageImage.setHeight(this.height + "px"); } private Point resize(int x, int y, int newwidth, int newheight) { float constantx = (float) x / (float) this.width; float constanty = (float) y / (float) this.height; int newposx = Math.round((float) constantx * newwidth); int newposy = Math.round((float) constanty * newheight); return new Point(newposx, newposy); } }