diff --git a/colors/almost_gray1.yml b/colors/almost_gray1.yml new file mode 100644 index 0000000..52e1639 --- /dev/null +++ b/colors/almost_gray1.yml @@ -0,0 +1,3 @@ +{OKAY: '#ACB5AC', SELECTED_TASK: '#D4DAD4', BACKGROUND: '#1c1d1d', TASK: '#38753C', + TODO: '#848A8B', TEXT: '#F2EFEC', FAIL: '#E6DADA', LINE: '#BFC5C5', WARN: '#E6DFDA', + HOVER: '#F2EDE9'} diff --git a/colors/blue.yml b/colors/blue.yml new file mode 100644 index 0000000..3d218dc --- /dev/null +++ b/colors/blue.yml @@ -0,0 +1,3 @@ +{OKAY: '#3E7F89', SELECTED_TASK: '#5F9EA6', BACKGROUND: '#1c1d1d', TASK: '#266871', + TODO: '#4C5F97', TEXT: '#E7C783', FAIL: '#DF9E62', LINE: '#6D7EB1', WARN: '#DFB862', + HOVER: '#E7C376'} diff --git a/color.yml b/colors/colors1.yml similarity index 66% rename from color.yml rename to colors/colors1.yml index 6ffa6d6..35319e9 100644 --- a/color.yml +++ b/colors/colors1.yml @@ -1,3 +1,3 @@ {OKAY: '#03CA03', SELECTED_TASK: '#67E667', BACKGROUND: '#1c1d1d', TASK: '#008500', - TODO: '#029898', TEXT: '#f9b175', FAIL: '#FD0404', LINE: '#5CCCCC', WARN: '#FD7504', + TODO: '#029898', TEXT: '#E8E2DD', FAIL: '#FD0404', LINE: '#5CCCCC', WARN: '#FD7504', HOVER: '#ff9640'} diff --git a/colors/colors2.yml b/colors/colors2.yml new file mode 100644 index 0000000..91f5deb --- /dev/null +++ b/colors/colors2.yml @@ -0,0 +1,3 @@ +{OKAY: '#01939A', SELECTED_TASK: '#5DC8CD', BACKGROUND: '#1c1d1d', TASK: '#006064', + TODO: '#123EAB', TEXT: '#FFD173', FAIL: '#FF7600', LINE: '#6C8AD5', WARN: '#FFAB00', + HOVER: '#FFC040'} diff --git a/colors/easter.yml b/colors/easter.yml new file mode 100644 index 0000000..44ef24e --- /dev/null +++ b/colors/easter.yml @@ -0,0 +1,3 @@ +{OKAY: '#ABD15C', SELECTED_TASK: '#BEDC7D', BACKGROUND: '#1c1d1d', TASK: '#87AC39', + TODO: '#55B550', TEXT: '#E68285', FAIL: '#B14E88', LINE: '#75C771', WARN: '#DD6164', + HOVER: '#E67578'} diff --git a/colors/halloween.yml b/colors/halloween.yml new file mode 100644 index 0000000..317f570 --- /dev/null +++ b/colors/halloween.yml @@ -0,0 +1,3 @@ +{OKAY: '#8F813F', SELECTED_TASK: '#AB9E61', BACKGROUND: '#1c1d1d', TASK: '#766827', + TODO: '#8F8E3F', TEXT: '#735087', FAIL: '#3D3262', LINE: '#ABAA61', WARN: '#4D2D5F', + HOVER: '#704987'} diff --git a/colors/high_contrast.yml b/colors/high_contrast.yml new file mode 100644 index 0000000..eb1e805 --- /dev/null +++ b/colors/high_contrast.yml @@ -0,0 +1,3 @@ +{OKAY: '#12B51D', SELECTED_TASK: '#A7ECAC', BACKGROUND: '#1c1d1d', TASK: '#025608', + TODO: '#0F858B', TEXT: '#F9D2B0', FAIL: '#E61C17', LINE: '#A0DFE2', WARN: '#E67617', + HOVER: '#F9AD6D'} diff --git a/colors/light1.yml b/colors/light1.yml new file mode 100644 index 0000000..0737a07 --- /dev/null +++ b/colors/light1.yml @@ -0,0 +1,3 @@ +{OKAY: '#003D00', SELECTED_TASK: '#196E19', BACKGROUND: '#eceded', TASK: '#003200', + TODO: '#002E2E', TEXT: '#79461B', FAIL: '#4D0000', LINE: '#166262', WARN: '#4D2300', + HOVER: '#793F0F'} diff --git a/colors/pastel1.yml b/colors/pastel1.yml new file mode 100644 index 0000000..dd6a7cf --- /dev/null +++ b/colors/pastel1.yml @@ -0,0 +1,3 @@ +{OKAY: '#4DB054', SELECTED_TASK: '#6FC374', BACKGROUND: '#1c1d1d', TASK: '#309136', + TODO: '#3C8487', TEXT: '#E7B183', FAIL: '#DF6562', LINE: '#5EA2A5', WARN: '#DF9C62', + HOVER: '#E7AA76'} diff --git a/src/com/adamldavis/z/Z.java b/src/com/adamldavis/z/Z.java index b2a6758..f4c50a1 100644 --- a/src/com/adamldavis/z/Z.java +++ b/src/com/adamldavis/z/Z.java @@ -3,8 +3,11 @@ import static java.util.Arrays.asList; +import java.awt.BorderLayout; +import java.awt.Container; import java.awt.Cursor; import java.awt.Dimension; +import java.awt.FlowLayout; import java.awt.Point; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -32,6 +35,8 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import javax.swing.JPanel; +import javax.swing.JScrollPane; import javax.swing.SwingUtilities; import org.slf4j.Logger; @@ -46,10 +51,13 @@ import com.adamldavis.z.editor.ZCodeEditor; import com.adamldavis.z.editor.ZCodeEditorPlus; import com.adamldavis.z.git.GitLogDiffsMap; +import com.adamldavis.z.gui.ColorManager; +import com.adamldavis.z.gui.ColorSetting; import com.adamldavis.z.gui.ZMenu; import com.adamldavis.z.gui.swing.ZDisplay; import com.adamldavis.z.tasks.ZTask; import com.adamldavis.z.tasks.ZTaskList; +import com.adamldavis.z.util.ThreadingUtil; /** * Main class of Z program. @@ -60,9 +68,9 @@ public class Z implements MouseListener, MouseWheelListener, MouseMotionListener, KeyListener, Runnable { - /** what's happening right now. */ - public enum State { - NORMAL, SELECTING, ANIMATING, EDITING, TIME_TRAVEL + /** Direction from "dependencies" to "sub-modules". */ + public enum Direction { + LR, RL, UP, DOWN }; /** organization of nodes. */ @@ -75,13 +83,17 @@ public enum SortOrder { DEFAULT, ALPHA, TIME, SIZE } - /** Direction from "dependencies" to "sub-modules". */ - public enum Direction { - LR, RL, UP, DOWN + /** what's happening right now. */ + public enum State { + NORMAL, SELECTING, ANIMATING, EDITING, TIME_TRAVEL } private static final Logger log = LoggerFactory.getLogger(Z.class); + public static float logSize(int size) { + return (float) (size > 2 ? Math.log(size) : 0); + } + public static void main(String[] args) { new Z(); } @@ -116,10 +128,7 @@ public void actionPerformed(ActionEvent e) { display.removeMouseMotionListener(zMenu); display.removeMouseListener(zMenu); saveSettings(); - display.addMouseWheelListener(Z.this); - display.addMouseListener(Z.this); - display.addMouseMotionListener(Z.this); - display.addKeyListener(Z.this); + addListeners(); } }); @@ -137,13 +146,30 @@ public void actionPerformed(ActionEvent e) { private final ZTaskList taskList = new ZTaskList(); - public GitLogDiffsMap diffsMap; // TODO make this an API + AtomicInteger count = new AtomicInteger(0); + + AtomicInteger aniCount = new AtomicInteger(0); + + final Map pointMap = new HashMap(); + + final Map sizeMap = new HashMap(); + + ZNodePositioner nodePositioner; + + SmoothAnimator animator = new SmoothAnimator(); + + ZNode selectedNode; + + final List zNodes = new ArrayList(); + + float scale = 1.0f; + + public ZFactory zfactory; + + public GitLogDiffsMap diffsMap; public Z() { - display.addMouseWheelListener(this); - display.addMouseListener(this); - display.addMouseMotionListener(this); - display.addKeyListener(this); + addListeners(); zfactory = new ZFactory(Z.class.getResourceAsStream("z.properties")); loadSettings(); timer.schedule(new TimerTask() { @@ -154,148 +180,29 @@ public void run() { }, 33, 33); } - @Override - public void mouseWheelMoved(MouseWheelEvent e) { - if (e.isControlDown()) { - log.debug("zoom:" + e.getWheelRotation()); - if (e.getWheelRotation() > 0 && scale > 0.125f) { - scale /= 2f; - } else if (e.getWheelRotation() < 0 && scale < 32) { - scale *= 2f; - } - log.debug("Scale:" + scale); - if (!editors.isEmpty()) { - for (Editor editor : editors) { - editor.setScale(scale); - } - } - } - } - - @Override - public void mouseDragged(MouseEvent e) { - if (e.getButton() != MouseEvent.BUTTON3) { - point2 = e.getPoint(); - } - } - - @Override - public void mousePressed(MouseEvent e) { - log.info("pressed: " + e); - if (e.getButton() != MouseEvent.BUTTON3) { - point1 = e.getPoint(); - } - ZNode z = findZNodeAt(e.getPoint()); - if (z != null) { - if (e.isControlDown()) { - // new code editor - showNewEditor(z); - } else if (e.getButton() == MouseEvent.BUTTON1) { - draggedNode = z; - } - } - } - - @Override - public void mouseReleased(MouseEvent e) { - log.info("released: " + e); - if (point1 != null && point2 != null) { - if (draggedNode == null) { - ZNode z = findZNodeAt(e.getPoint()); - if (z == null) { - createSubNode(e.getPoint()); - } else - dragged(z); - } else if (e.getPoint().y >= display.getHeight() - 40) { - final ZTask task = taskList.getTaskAt(e.getPoint().x, 20); - if (task == null) { - // TODO: show confirmation? - synchronized (zNodes) { - zNodes.remove(draggedNode); - } - } else - task.add(draggedNode); - draggedNode = null; - } else { - draggedNode.getLocation().setLocation( - translateToZNodePoint(point2)); - updateSubLocations(draggedNode); - draggedNode = null; - } - point1 = point2 = null; - } - } - - @Override - public void mouseClicked(MouseEvent e) { - final Point p = e.getPoint(); - ZNode z = findZNodeAt(p); - - if (z == null) { - zMenu.setVisible(false); - if (e.getButton() == MouseEvent.BUTTON3) { - activateMenu(e); - } else if (p.y >= display.getHeight() - 40) { - final ZTask task = taskList.getTaskAt(p.x, 20); - selectTask(task); - } else if (selectedNode == null) { - selectedNode = createNewZ(p, ZNodeType.MODULE); - } else { - createNewZ(p, ZNodeType.DEPENDENCY); - } - } else if (e.getButton() == MouseEvent.BUTTON1 && !e.isControlDown()) { - clicked(z); - } - } - - @Override - public void mouseMoved(MouseEvent e) { - final ZNode node = findZNodeAt(e.getPoint()); - if (node == selectedNode) { - return; - } - if (hoveredNode != node && hoveredNode != null) { - hoveredNode.setSize(hoveredNode.getSize() * 1f / 1.1f); - } - if (node != null && hoveredNode != node) { - node.setSize(node.getSize() * 1.1f); - } - hoveredNode = node; - hoverText = node == null ? null : node.getName(); - mouseLocation = e.getPoint(); + private void addListeners() { + display.addMouseWheelListener(Z.this); + display.addMouseListener(Z.this); + display.addMouseMotionListener(Z.this); + display.addKeyListener(Z.this); } - @Override - public void keyReleased(KeyEvent e) { - links.clear(); - } + public void activateGoUp() { + File pFile = selectedNode.getParentFile(); - @Override - public void keyPressed(KeyEvent e) { - if (!links.isEmpty()) - return; - switch (e.getKeyChar()) { - case 'm': - if (selectedNode.getNodeType() == ZNodeType.CLASS) { - addMethodLinks(); + if (selectedNode.getNodeType() == ZNodeType.PACKAGE) { + for (int i = 0; i < selectedNode.getName().split("\\.").length; i++) { + pFile = pFile.getParentFile(); } - break; - case 'p': - // TODO: add polymorphic links - case 'i': - case 'r': - // TODO: add import/require links - case 'h': - case 'f': - addFieldLinks(); + } else if (selectedNode.getNodeType() == ZNodeType.MODULE) { + pFile = pFile.getParentFile(); } + selectedNode = new ZCodeLoader(apiFactory).load(pFile); + clicked(selectedNode); } protected void activateMenu(MouseEvent e) { - display.removeMouseWheelListener(Z.this); - display.removeMouseListener(Z.this); - display.removeMouseMotionListener(Z.this); - display.removeKeyListener(Z.this); + removeListeners(); zMenu.setLocation(e.getPoint()); display.addMouseListener(zMenu); display.addMouseMotionListener(zMenu); @@ -308,58 +215,68 @@ public void run() { }); } - public void activateGoUp() { - File pFile = selectedNode.getParentFile(); + private void removeListeners() { + display.removeMouseWheelListener(Z.this); + display.removeMouseListener(Z.this); + display.removeMouseMotionListener(Z.this); + display.removeKeyListener(Z.this); + } - if (selectedNode.getNodeType() == ZNodeType.PACKAGE) { - for (int i = 0; i < selectedNode.getName().split("\\.").length; i++) { - pFile = pFile.getParentFile(); + protected void addFieldLinks() { + log.info("addFieldLinks()"); + final Map nodeMap = new HashMap(); + final Pattern patt = Pattern + .compile("(private |protected |public |final |static )+\\s*(\\w+)"); + + // TODO redo this to actually include packages + for (ZNode node : selectedNode.getSubmodules()) { + if (node.getNodeType() == ZNodeType.CLASS) { + nodeMap.put(node.getName(), node); } - } else if (selectedNode.getNodeType() == ZNodeType.MODULE) { - pFile = pFile.getParentFile(); } - selectedNode = new ZCodeLoader(apiFactory).load(pFile); - clicked(selectedNode); + log.info("nodeMap={}", nodeMap); + for (ZNode node : selectedNode.getSubmodules()) { + for (String line : node.getCodeLines()) { + final Matcher matcher = patt.matcher(line); + if (matcher.find()) { + log.info("group2={}", matcher.group(2)); + if (nodeMap.containsKey(matcher.group(2))) { + links.add(new ZNodeLink(node, nodeMap.get(matcher + .group(2)), LinkType.HAS_A)); + } + } + } + } + // just add 1 so there's at least 1 + links.add(new ZNodeLink(selectedNode, selectedNode, LinkType.HAS_A)); } - private void loadSettings() { - if (settings.getProperty(UserSettings.DIRECTION) != null) { - direction = Direction.valueOf(settings - .getProperty(UserSettings.DIRECTION)); - nodeLayout = NodeLayout.valueOf(settings - .getProperty(UserSettings.LAYOUT)); - order = SortOrder.valueOf(settings.getProperty(UserSettings.ORDER)); + private void addMethodLinks() { + log.info("addMethodLinks()"); + final Map nodeMap = new HashMap(); + final Pattern patt = Pattern.compile("(\\w+)\\("); + + for (ZNode method : selectedNode.getSubmodules()) { + final Matcher matcher = patt.matcher(method.getName()); + if (matcher.find()) { + final String name = matcher.group(1); + nodeMap.put(name, method); + } } - if (settings.getProperty(UserSettings.LAST_LOCATION) != null) { - final File file = settings.getFile(UserSettings.LAST_LOCATION); - clicked(load(file)); + log.info("nodeMap={}", nodeMap); + for (ZNode method : selectedNode.getSubmodules()) { + for (ZNode call : method.getSubmodules()) { + // TODO fix + if (nodeMap.containsKey(call.getName())) { + links.add(new ZNodeLink(method, + nodeMap.get(call.getName()), LinkType.METHOD_CALL)); + } + } } + // just add 1 so there's at least 1 + links.add(new ZNodeLink(selectedNode, selectedNode, LinkType.HAS_A)); } - public void saveSettings() { - settings.setProperty(UserSettings.DIRECTION, direction.toString()); - settings.setProperty(UserSettings.LAYOUT, nodeLayout.toString()); - settings.setProperty(UserSettings.ORDER, order.toString()); - settings.save(); - } - - protected void dragged(ZNode z) { - log.info("dragged: " + z); - // create dependency on z? - if (z.getNodeType() == ZNodeType.DEPENDENCY) - selectedNode.getDependencies().add(z); - } - - AtomicInteger count = new AtomicInteger(0); - - AtomicInteger aniCount = new AtomicInteger(0); - - final Map pointMap = new HashMap(); - - final Map sizeMap = new HashMap(); - - ZNodePositioner nodePositioner; - protected void clicked(ZNode node) { log.info("selected: " + node); selectedNode = new ZCodeLoader(apiFactory).load(node); @@ -374,198 +291,29 @@ protected void clicked(ZNode node) { state = State.ANIMATING; aniCount.set(0); final Dimension dim = display.getDimension(); - nodePositioner = new PixelZNodePositioner(dim, - new DirectionZNodePositioner(direction, makeNodePositioner())); sortNodes(); - pointMap.putAll(nodePositioner.getNewPositions(selectedNode)); - sizeMap.put(selectedNode, - (float) Math.min(dim.getWidth(), dim.getHeight()) / 2); - Map depMap = new HashMap(); + float selSize = (float) Math.min(dim.getWidth(), dim.getHeight()) / 2.2f; + sizeMap.put(selectedNode, selSize); + float shrinkFactor = 0.2f; + float size = (float) (selSize * shrinkFactor); for (ZNode dep : selectedNode.getDependencies()) { - depMap.put(dep, pointMap.get(dep)); + sizeMap.put(dep, size); } for (ZNode sub : selectedNode.getSubmodules()) { - Point2D loc = pointMap.get(sub); - final Point center = new Point((int) Math.round(loc.getX()), - (int) Math.round(loc.getY())); sub = new ZCodeLoader(apiFactory).load(sub); - float size = (float) (dim.getHeight() * 0.10416666666666); sizeMap.put(sub, size + logSize(sub.getSubmodules().size())); synchronized (zNodes) { zNodes.addAll(sub.getSubmodules()); } for (ZNode sub2 : sub.getSubmodules()) { - sizeMap.put(sub2, size / 8f + logSize(sub2.getCodeLineSize())); - } - pointMap.putAll(new PixelZNodePositioner(center, new Dimension( - dim.width / 10, dim.height / 10), - new DirectionZNodePositioner(direction, - makeNodePositioner())).getNewPositions(sub)); - } - pointMap.putAll(depMap); - } - - public static float logSize(int size) { - return (float) (size > 2 ? Math.log(size) : 0); - } - - private void sortNodes() { - Collections.sort(selectedNode.getSubmodules(), new Comparator() { - - @Override - public int compare(ZNode node1, ZNode node2) { - switch (order) { - case ALPHA: - return node1.getName().compareTo(node2.getName()); - case SIZE: - return node1.getCodeLineSize() - node2.getCodeLineSize(); - case TIME: - return (int) (node1.getLastModified() - node2 - .getLastModified()); - default: - return 0; - } - } - - }); - } - - private ZNodePositioner makeNodePositioner() { - switch (nodeLayout) { - case BLOOM: - return new BloomZNodePositioner(); - case RANDOM: - return new RandomZNodePositioner(); - default: - return new GridZNodePositioner(); - } - } - - SmoothAnimator animator = new SmoothAnimator(); - - ZNode selectedNode; - - final List zNodes = new ArrayList(); - - float scale = 1.0f; - - public ZFactory zfactory; - - @Override - public void run() { - if ((state == State.ANIMATING && aniCount.incrementAndGet() >= 100) - || (state == State.TIME_TRAVEL && aniCount.addAndGet(1) >= 999) - || (state == State.SELECTING && aniCount.addAndGet(2) >= 100)) { - if (state == State.ANIMATING || state == State.TIME_TRAVEL) { - state = State.NORMAL; - links.clear(); - } else if (state == State.SELECTING) { - if (editors.isEmpty()) { - state = State.NORMAL; - } else { - state = State.EDITING; - } - } - } - count.incrementAndGet(); - if (count.get() >= 20) { - count.set(0); - } - final float time = aniCount.get() / 100f; - - if (getState() == State.SELECTING) { - Editor ed = getEditors().get(0); - int y = 8 + (editors.size() == 1 ? 0 : editors.get(1) - .getEditorPanel().getY() - + editors.get(1).getEditorPanel().getHeight()); - ed.setScale(0.25f + 0.75f * time); - final Point2D point = animator.animate(getSelectedNode() - .getLocation(), new Point2D.Float(8, y), time, - AnimationType.COSINE); - ed.getEditorPanel().setLocation((int) point.getX(), - (int) point.getY()); - } else if (getState() == State.ANIMATING) - synchronized (zNodes) { - for (ZNode node : zNodes) { - if (pointMap.containsKey(node)) { - node.getLocation().setLocation( - animator.animate(node.getLocation(), - pointMap.get(node), time, - AnimationType.COSINE)); - } - if (sizeMap.containsKey(node)) { - final Float size = sizeMap.get(node); - final Float currentSize = node.getSize(); - node.setSize((float) animator.animate( - new Point2D.Float(currentSize, 0), - new Point2D.Float(size, 0), time, - AnimationType.COSINE).getX()); - } - } - } - else if (getState() == State.TIME_TRAVEL - && aniCount.get() * diffsMap.getLogSize() / 1000 > (aniCount - .get() - 1) * diffsMap.getLogSize() / 1000) - synchronized (zNodes) { - final Collection nodeLinks = diffsMap.getNodeLinks( - aniCount.get() * diffsMap.getLogSize() / 1000, zNodes); - if (!nodeLinks.isEmpty()) { - links.clear(); - links.addAll(nodeLinks); - } - } - else if (getState() == State.TIME_TRAVEL) { - if (diffsMap.author != null) { - ZNode node = diffsMap.author; - float t = aniCount.get() % 100 / 100f; - - node.getLocation().setLocation( - animator.animate(node.getLocation(), - diffsMap.authorLocation, t, - AnimationType.COSINE)); - } - } - } - - ZNode findZNodeAt(Point p) { - ZNode found = null; - synchronized (zNodes) { - for (ZNode z : zNodes) { - final double hs = z.getSize() * scale * 0.5; - if (translateToDisplayPoint(z.getLocation()).distance(p.x, p.y) < hs) { - found = z; - } - } - } - return found; - } - - public void createSubNode(Point point) { - if (selectedNode != null) { - // create sub-module - final ZNodeType subtype; - switch (selectedNode.getNodeType()) { - case METHOD: - subtype = ZNodeType.CALLEE; - break; - case CLASS: - subtype = ZNodeType.METHOD; - break; - case PACKAGE: - subtype = ZNodeType.CLASS; - break; - case CALLEE: - case CALLER: - case DEPENDENCY: - return; - default: - subtype = ZNodeType.PACKAGE; + sizeMap.put(sub2, + size * shrinkFactor + logSize(sub2.getCodeLineSize())); } - ZNode sub = createNewZ(point, subtype); - if (sub != null) - selectedNode.getSubmodules().add(sub); } + Point2D.Float center = new Point2D.Float(selSize * 1.25f, selSize); + pointMap.put(node, center); + updateSubLocations(selectedNode, false, center); } ZNode createNewZ(final Point point, final ZNodeType type) { @@ -618,155 +366,484 @@ private ZNode createNewZNode(Point point, ZNodeType type, String name) { return zNode; } - public ZNode load(File file) { - apiFactory = zfactory.getApiFactory(file); - log.info("api=" + apiFactory); - final ZNode node = new ZCodeLoader(apiFactory).load(file); - selectedNode = node; - return node; + public void createSubNode(Point point) { + if (selectedNode != null) { + // create sub-module + final ZNodeType subtype; + switch (selectedNode.getNodeType()) { + case METHOD: + subtype = ZNodeType.CALLEE; + break; + case CLASS: + subtype = ZNodeType.METHOD; + break; + case PACKAGE: + subtype = ZNodeType.CLASS; + break; + case CALLEE: + case CALLER: + case DEPENDENCY: + return; + default: + subtype = ZNodeType.PACKAGE; + } + ZNode sub = createNewZ(point, subtype); + if (sub != null) + selectedNode.getSubmodules().add(sub); + } } - /** Translates from location as stored for ZNodes to GUI point. */ - public Point2D.Float translateToDisplayPoint(Point2D.Float point) { - return new Point2D.Float(point.x * scale, point.y * scale); + protected void dragged(ZNode z) { + log.info("dragged: " + z); + // create dependency on z? + if (z.getNodeType() == ZNodeType.DEPENDENCY) + selectedNode.getDependencies().add(z); } - /** Translates from GUI point to location as stored for ZNodes. */ - public Point2D.Float translateToZNodePoint(Point point) { - return new Point2D.Float(point.x / scale, point.y / scale); + ZNode findZNodeAt(Point p) { + ZNode found = null; + synchronized (zNodes) { + for (ZNode z : zNodes) { + final double hs = z.getSize() * scale * 0.5; + if (translateToDisplayPoint(z.getLocation()).distance(p.x, p.y) < hs) { + found = z; + } + } + } + return found; } - public List getZNodes() { - return this.zNodes; + public AtomicInteger getAniCount() { + return aniCount; + } + + public SmoothAnimator getAnimator() { + return animator; } public APIFactory getApiFactory() { return apiFactory; } - public Point getPoint1() { - return point1; + public AtomicInteger getCount() { + return count; } - public Point getPoint2() { - return point2; + public Direction getDirection() { + return direction; } - public State getState() { - return state; + public ZDisplay getDisplay() { + return display; } - public NodeLayout getNodeLayout() { - return nodeLayout; + public ZNode getDraggedNode() { + return draggedNode; } - public Direction getDirection() { - return direction; + public List getEditors() { + return editors; } - public ZNode getDraggedNode() { - return draggedNode; + public ZNode getHoveredNode() { + return hoveredNode; } - public List getEditors() { - return editors; + public String getHoverText() { + return hoverText; + } + + public List getLinks() { + return links; + } + + public ZMenu getMenu() { + return this.zMenu; + } + + public Point getMouseLocation() { + return mouseLocation; + } + + public NodeLayout getNodeLayout() { + return nodeLayout; + } + + public ZNodePositioner getNodePositioner() { + return nodePositioner; } public SortOrder getOrder() { return order; } + public Point getPoint1() { + return point1; + } + + public Point getPoint2() { + return point2; + } + + public Map getPointMap() { + return pointMap; + } + + public float getScale() { + return scale; + } + + public ZNode getSelectedNode() { + return selectedNode; + } + public UserSettings getSettings() { return settings; } - public ZDisplay getDisplay() { - return display; + public State getState() { + return state; } - public AtomicInteger getCount() { - return count; + public ZTaskList getTaskList() { + return taskList; } - public AtomicInteger getAniCount() { - return aniCount; + public List getZNodes() { + return this.zNodes; + } + + @Override + public void keyPressed(KeyEvent e) { + if (!links.isEmpty()) + return; + switch (e.getKeyChar()) { + case 'm': + if (selectedNode.getNodeType() == ZNodeType.CLASS) { + addMethodLinks(); + } + break; + case 'p': + // TODO: add polymorphic links + case 'i': + case 'r': + // TODO: add import/require links + case 'h': + case 'f': + addFieldLinks(); + } + } + + @Override + public void keyReleased(KeyEvent e) { + links.clear(); + } + + @Override + public void keyTyped(KeyEvent e) { + // TODO Auto-generated method stub + } + + public ZNode load(File file) { + apiFactory = zfactory.getApiFactory(file); + log.info("api=" + apiFactory); + final ZNode node = new ZCodeLoader(apiFactory).load(file); + selectedNode = node; + return node; + } + + private void loadSettings() { + if (settings.getProperty(UserSettings.DIRECTION) != null) { + direction = Direction.valueOf(settings + .getProperty(UserSettings.DIRECTION)); + nodeLayout = NodeLayout.valueOf(settings + .getProperty(UserSettings.LAYOUT)); + order = SortOrder.valueOf(settings.getProperty(UserSettings.ORDER)); + } + if (settings.getProperty(UserSettings.LAST_LOCATION) != null) { + final File file = settings.getFile(UserSettings.LAST_LOCATION); + clicked(load(file)); + } + } + + private ZNodePositioner makeNodePositioner() { + switch (nodeLayout) { + case BLOOM: + return new BloomZNodePositioner(); + case RANDOM: + return new RandomZNodePositioner(); + default: + return new GridZNodePositioner(); + } + } + + @Override + public void mouseClicked(MouseEvent e) { + final Point p = e.getPoint(); + ZNode z = findZNodeAt(p); + + if (z == null) { + zMenu.setVisible(false); + if (e.getButton() == MouseEvent.BUTTON3) { + activateMenu(e); + } else if (p.y >= display.getHeight() - 40) { + final ZTask task = taskList.getTaskAt(p.x, 20); + selectTask(task); + } else if (selectedNode == null) { + selectedNode = createNewZ(p, ZNodeType.MODULE); + } else { + createNewZ(p, ZNodeType.DEPENDENCY); + } + } else if (e.getButton() == MouseEvent.BUTTON1 && !e.isControlDown()) { + clicked(z); + } } - public Map getPointMap() { - return pointMap; + @Override + public void mouseDragged(MouseEvent e) { + if (e.getButton() != MouseEvent.BUTTON3) { + point2 = e.getPoint(); + } + } + + @Override + public void mouseEntered(MouseEvent e) { + // TODO Auto-generated method stub + } + + @Override + public void mouseExited(MouseEvent e) { + // TODO Auto-generated method stub + } + + @Override + public void mouseMoved(MouseEvent e) { + final ZNode node = findZNodeAt(e.getPoint()); + if (node == selectedNode) { + return; + } + if (hoveredNode != node && hoveredNode != null) { + hoveredNode.setSize(hoveredNode.getSize() * 1f / 1.1f); + } + if (node != null && hoveredNode != node) { + node.setSize(node.getSize() * 1.1f); + } + hoveredNode = node; + hoverText = node == null ? null : node.getName(); + mouseLocation = e.getPoint(); + } + + @Override + public void mousePressed(MouseEvent e) { + log.info("pressed: " + e); + if (e.getButton() != MouseEvent.BUTTON3) { + point1 = e.getPoint(); + } + ZNode z = findZNodeAt(e.getPoint()); + if (z != null) { + if (e.isControlDown()) { + // new code editor + showNewEditor(z); + } else if (e.getButton() == MouseEvent.BUTTON1) { + draggedNode = z; + } + } + } + + @Override + public void mouseReleased(MouseEvent e) { + log.info("released: " + e); + if (point1 != null && point2 != null) { + if (draggedNode == null) { + ZNode z = findZNodeAt(e.getPoint()); + if (z == null) { + createSubNode(e.getPoint()); + } else + dragged(z); + } else if (e.getPoint().y >= display.getHeight() - 40) { + final ZTask task = taskList.getTaskAt(e.getPoint().x, 20); + if (task == null) { + // TODO: show confirmation? + synchronized (zNodes) { + zNodes.remove(draggedNode); + } + } else + task.add(draggedNode); + draggedNode = null; + } else { + draggedNode.getLocation().setLocation( + translateToZNodePoint(point2)); + updateSubLocations(draggedNode, true, draggedNode.getLocation()); + draggedNode = null; + } + point1 = point2 = null; + } + } + + @Override + public void mouseWheelMoved(MouseWheelEvent e) { + if (e.isControlDown()) { + log.debug("zoom:" + e.getWheelRotation()); + if (e.getWheelRotation() > 0 && scale > 0.125f) { + scale /= 2f; + } else if (e.getWheelRotation() < 0 && scale < 32) { + scale *= 2f; + } + log.debug("Scale:" + scale); + if (!editors.isEmpty()) { + for (Editor editor : editors) { + editor.setScale(scale); + } + } + } + } + + @Override + public void run() { + if ((state == State.ANIMATING && aniCount.incrementAndGet() >= 100) + || (state == State.TIME_TRAVEL && aniCount.addAndGet(1) >= 999) + || (state == State.SELECTING && aniCount.addAndGet(2) >= 100)) { + if (state == State.ANIMATING || state == State.TIME_TRAVEL) { + state = State.NORMAL; + links.clear(); + } else if (state == State.SELECTING) { + if (editors.isEmpty()) { + state = State.NORMAL; + } else { + state = State.EDITING; + } + } + } + count.incrementAndGet(); + if (count.get() >= 20) { + count.set(0); + } + final float time = aniCount.get() / 100f; + + if (getState() == State.SELECTING) { + Editor ed = getEditors().get(0); + int y = 8 + (editors.size() == 1 ? 0 : editors.get(1) + .getEditorPanel().getY() + + editors.get(1).getEditorPanel().getHeight()); + ed.setScale(0.25f + 0.75f * time); + final Point2D point = animator.animate(getSelectedNode() + .getLocation(), new Point2D.Float(8, y), time, + AnimationType.COSINE); + ed.getEditorPanel().setLocation((int) point.getX(), + (int) point.getY()); + } else if (getState() == State.ANIMATING) + synchronized (zNodes) { + for (ZNode node : zNodes) { + if (pointMap.containsKey(node)) { + node.getLocation().setLocation( + animator.animate(node.getLocation(), + pointMap.get(node), time, + AnimationType.COSINE)); + } + if (sizeMap.containsKey(node)) { + final Float size = sizeMap.get(node); + final Float currentSize = node.getSize(); + node.setSize((float) animator.animate( + new Point2D.Float(currentSize, 0), + new Point2D.Float(size, 0), time, + AnimationType.COSINE).getX()); + } + } + } + else if (getState() == State.TIME_TRAVEL + && aniCount.get() * diffsMap.getLogSize() / 1000 > (aniCount + .get() - 1) * diffsMap.getLogSize() / 1000) + synchronized (zNodes) { + final Collection nodeLinks = diffsMap.getNodeLinks( + aniCount.get() * diffsMap.getLogSize() / 1000, zNodes); + if (!nodeLinks.isEmpty()) { + links.clear(); + links.addAll(nodeLinks); + } + } + else if (getState() == State.TIME_TRAVEL) { + if (diffsMap.author != null) { + ZNode node = diffsMap.author; + float t = aniCount.get() % 100 / 100f; + + node.getLocation().setLocation( + animator.animate(node.getLocation(), + diffsMap.authorLocation, t, + AnimationType.COSINE)); + } + } } - public ZNodePositioner getNodePositioner() { - return nodePositioner; + public void saveSettings() { + settings.setProperty(UserSettings.DIRECTION, direction.toString()); + settings.setProperty(UserSettings.LAYOUT, nodeLayout.toString()); + settings.setProperty(UserSettings.ORDER, order.toString()); + settings.save(); } - public SmoothAnimator getAnimator() { - return animator; + private void selectTask(final ZTask task) { + if (task == taskList.getActiveTask()) { + taskList.setActiveTask(null); + clicked(selectedNode); + return; + } else if (task != null) { + taskList.setActiveTask(task); + } + if (task.getNodes().isEmpty()) { + clicked(selectedNode); + } else { + synchronized (zNodes) { + zNodes.clear(); + zNodes.addAll(task.getNodes()); + } + } } - public ZNode getSelectedNode() { - return selectedNode; + public void setDirection(Direction direction) { + this.direction = direction; } - public float getScale() { - return scale; + public void setHoverText(String hoverText) { + this.hoverText = hoverText; } public void setNodeLayout(NodeLayout nodeLayout) { this.nodeLayout = nodeLayout; } - public void setDirection(Direction direction) { - this.direction = direction; - } - public void setOrder(SortOrder order) { this.order = order; } + public void setState(State state) { + this.state = state; + } + + final Container pane = new JPanel(new FlowLayout(FlowLayout.LEFT)); + public void showNewEditor(final ZNode z) { - selectedNode = z; + removeListeners(); final ZCodeEditor editor = z.getNodeType() == ZNodeType.METHOD ? new ZCodeEditorPlus( z, apiFactory) : new ZCodeEditor(z, apiFactory); - final KeyListener keyAdapter = new KeyListener() { - - @Override - public void keyTyped(KeyEvent e) { - if (e.getKeyChar() == '\n') { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - try { - Thread.sleep(100); // 1/10 second - } catch (InterruptedException e) { - } - editor.save(); - Swutil.flashMessage(display, "Saved " + z.getName()); - } - }); - } - } + final JScrollPane scrollPane = new JScrollPane(pane); + pane.setMaximumSize(new Dimension(display.getWidth(), Integer.MAX_VALUE)); + display.getContentPane().setLayout(new BorderLayout()); + display.getContentPane().add(scrollPane); + pane.setBackground(new ColorManager() + .getColorFor(ColorSetting.BACKGROUND)); - @Override - public void keyReleased(KeyEvent e) { - } + final KeyListener keyAdapter = new KeyListener() { @Override public void keyPressed(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_ESCAPE) { - editor.save(); - for (Editor ed : editors) - display.getContentPane().remove(ed.getEditorPanel()); - - state = State.NORMAL; - display.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); - clicked(selectedNode); + endEditing(editor, pane, scrollPane); } else if (e.getKeyCode() == KeyEvent.VK_S && e.isControlDown()) { editor.save(); } else if (e.getKeyCode() == KeyEvent.VK_W && e.isControlDown()) { // close just this editor. editors.remove(editor); - display.getContentPane().remove(editor.getEditorPanel()); + pane.remove(editor.getEditorPanel()); display.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); } else if (e.getKeyCode() == KeyEvent.VK_F1) { try { @@ -777,153 +854,128 @@ public void keyPressed(KeyEvent e) { display.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); } } + + private void endEditing(final ZCodeEditor editor, + final Container pane, final JScrollPane scrollPane) { + editor.save(); + for (Editor ed : editors) + pane.remove(ed.getEditorPanel()); + + state = State.NORMAL; + display.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + addListeners(); + display.start(); + display.getContentPane().remove(scrollPane); + } + + @Override + public void keyReleased(KeyEvent e) { + } + + @Override + public void keyTyped(KeyEvent e) { + if (e.getKeyChar() == '\n') { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + try { + Thread.sleep(100); // 1/10 second + } catch (InterruptedException e) { + } + editor.save(); + Swutil.flashMessage(display, "Saved " + z.getName()); + } + }); + } + } }; editor.addKeyListener(keyAdapter); editors.add(0, editor); final int size = (int) z.getSize(); editor.getEditorPanel().setSize(new Dimension(size, size)); - for (Editor ed : editors) - display.getContentPane().add(ed.getEditorPanel()); + int maxW = 0, maxH = 0; + for (Editor ed : editors) { + maxW = Math.max(ed.getEditorPanel().getX() + + ed.getEditorPanel().getWidth(), maxW); + maxH = Math.max(ed.getEditorPanel().getY() + + ed.getEditorPanel().getHeight(), maxH); + pane.add(ed.getEditorPanel()); + } + pane.setPreferredSize(new Dimension(maxW, maxH)); editor.getEditorPanel().setLocation((int) z.getLocation().x - size / 2, (int) z.getLocation().y - size / 2); editor.setScale(0.25f); state = State.SELECTING; aniCount.set(10); - } - - public ZNode getHoveredNode() { - return hoveredNode; - } - - public String getHoverText() { - return hoverText; - } - - public void setHoverText(String hoverText) { - this.hoverText = hoverText; - } - - public Point getMouseLocation() { - return mouseLocation; - } - - private void addMethodLinks() { - log.info("addMethodLinks()"); - final Map nodeMap = new HashMap(); - final Pattern patt = Pattern.compile("(\\w+)\\("); - - for (ZNode method : selectedNode.getSubmodules()) { - final Matcher matcher = patt.matcher(method.getName()); - if (matcher.find()) { - final String name = matcher.group(1); - nodeMap.put(name, method); - } - } - log.info("nodeMap={}", nodeMap); - for (ZNode method : selectedNode.getSubmodules()) { - for (ZNode call : method.getSubmodules()) { - // TODO fix - if (nodeMap.containsKey(call.getName())) { - links.add(new ZNodeLink(method, - nodeMap.get(call.getName()), LinkType.METHOD_CALL)); - } + ThreadingUtil.runAsThread(new Runnable() { + @Override + public void run() { + display.stop(); + display.doLayout(); + display.getContentPane().doLayout(); + scrollPane.doLayout(); + pane.doLayout(); } - } - // just add 1 so there's at least 1 - links.add(new ZNodeLink(selectedNode, selectedNode, LinkType.HAS_A)); + }); } - protected void addFieldLinks() { - log.info("addFieldLinks()"); - final Map nodeMap = new HashMap(); - final Pattern patt = Pattern - .compile("(private |protected |public |final |static )+\\s*(\\w+)"); + private void sortNodes() { + Collections.sort(selectedNode.getSubmodules(), new Comparator() { - // TODO redo this to actually include packages - for (ZNode node : selectedNode.getSubmodules()) { - if (node.getNodeType() == ZNodeType.CLASS) { - nodeMap.put(node.getName(), node); - } - } - log.info("nodeMap={}", nodeMap); - for (ZNode node : selectedNode.getSubmodules()) { - for (String line : node.getCodeLines()) { - final Matcher matcher = patt.matcher(line); - if (matcher.find()) { - log.info("group2={}", matcher.group(2)); - if (nodeMap.containsKey(matcher.group(2))) { - links.add(new ZNodeLink(node, nodeMap.get(matcher - .group(2)), LinkType.HAS_A)); - } + @Override + public int compare(ZNode node1, ZNode node2) { + switch (order) { + case ALPHA: + return node1.getName().compareTo(node2.getName()); + case SIZE: + return node1.getCodeLineSize() - node2.getCodeLineSize(); + case TIME: + return (int) (node1.getLastModified() - node2 + .getLastModified()); + default: + return 0; } } - } - // just add 1 so there's at least 1 - links.add(new ZNodeLink(selectedNode, selectedNode, LinkType.HAS_A)); - } - public List getLinks() { - return links; + }); } - public ZTaskList getTaskList() { - return taskList; + /** Translates from location as stored for ZNodes to GUI point. */ + public Point2D.Float translateToDisplayPoint(Point2D.Float point) { + return new Point2D.Float(point.x * scale, point.y * scale); } - private void selectTask(final ZTask task) { - if (task == taskList.getActiveTask()) { - taskList.setActiveTask(null); - clicked(selectedNode); - return; - } else if (task != null) { - taskList.setActiveTask(task); - } - if (task.getNodes().isEmpty()) { - clicked(selectedNode); - } else { - synchronized (zNodes) { - zNodes.clear(); - zNodes.addAll(task.getNodes()); - } - } + /** Translates from GUI point to location as stored for ZNodes. */ + public Point2D.Float translateToZNodePoint(Point point) { + return new Point2D.Float(point.x / scale, point.y / scale); } - private void updateSubLocations(ZNode node) { - final Point2D loc = node.getLocation(); + private void updateSubLocations(ZNode node, boolean immediate, Point2D loc) { final Point center = new Point((int) Math.round(loc.getX()), (int) Math.round(loc.getY())); - final Dimension dim = display.getDimension(); + // make bigger when more nodes + final float factor = selectedNode == node ? (1.3f + logSize(node + .getSubmodules().size()) / 2.2f) : 1.2f; + int size = Math.round(sizeMap.get(node) * factor); + final float xRatio = display.getWidth() / display.getHeight(); Map map = new PixelZNodePositioner(center, - new Dimension(dim.width / 10, dim.height / 10), + new Dimension((int) (size * xRatio), size), new DirectionZNodePositioner(direction, makeNodePositioner())) .getNewPositions(node); - for (ZNode sub : node.getSubmodules()) { - sub.setLocation((java.awt.geom.Point2D.Float) map.get(sub)); - } - } - - public void setState(State state) { - this.state = state; - } - - public ZMenu getMenu() { - return this.zMenu; - } - @Override - public void keyTyped(KeyEvent e) { - // TODO Auto-generated method stub - } - - @Override - public void mouseEntered(MouseEvent e) { - // TODO Auto-generated method stub - } + for (ZNode sub : node.getSubmodules()) { + pointMap.put(sub, map.get(sub)); + if (immediate) + sub.setLocation((java.awt.geom.Point2D.Float) map.get(sub)); - @Override - public void mouseExited(MouseEvent e) { - // TODO Auto-generated method stub + updateSubLocations(sub, immediate, map.get(sub)); + } + if (node == selectedNode) + for (ZNode dep : node.getDependencies()) { + pointMap.put(dep, map.get(dep)); + if (immediate) + dep.setLocation((java.awt.geom.Point2D.Float) map.get(dep)); + } } - } diff --git a/src/com/adamldavis/z/ZCodeLoader.java b/src/com/adamldavis/z/ZCodeLoader.java index 715485a..c56b7de 100644 --- a/src/com/adamldavis/z/ZCodeLoader.java +++ b/src/com/adamldavis/z/ZCodeLoader.java @@ -208,6 +208,7 @@ public ZNode load(ZNode node) { for (ZNode method : methods) { method.setParentFile(file); + method.setParentNode(node); } node.getSubmodules().addAll(methods); node.getDependencies().clear(); diff --git a/src/com/adamldavis/z/ZCodeSaver.java b/src/com/adamldavis/z/ZCodeSaver.java index 6169303..178e2fa 100644 --- a/src/com/adamldavis/z/ZCodeSaver.java +++ b/src/com/adamldavis/z/ZCodeSaver.java @@ -4,6 +4,7 @@ import java.io.File; import java.io.IOException; +import java.util.Collections; import java.util.LinkedList; import java.util.List; @@ -47,8 +48,27 @@ public ZCodeSaver(CodeFormatter codeFormatter, private List getClassCode(ZNode zNode) { final List code = new LinkedList(zNode.getCodeLines()); int end = zNode.getEndLineNumber(languageParser); + int i = 0; - for (ZNode method : zNode.getSubmodules()) { + for (String line : zNode.getCodeLines()) { + i++; + if (line.startsWith(languageParser.getPackageKeyword())) { + break; + } + } + for (ZNode imp : zNode.getDependencies()) { + List imports = new LinkedList(imp.getCodeLines()); + Collections.reverse(imports); + for (String line : imports) { + code.add(i, languageParser.getImportKeyword() + " " + line + + (languageParser.requiresSemicolon() ? ";" : "")); + } + i += imp.getCodeLineSize(); + } + List methods = new LinkedList(zNode.getSubmodules()); + Collections.reverse(methods); + for (ZNode method : methods) { + code.add(""); code.addAll(end, method.getCodeLines()); } @@ -59,7 +79,8 @@ public void save(ZNode zNode) { switch (zNode.getNodeType()) { case CLASS: if ("".equals(zNode.getExtension())) { - zNode.setExtension(languageParser.getValidFileExtensions().get(0)); + zNode.setExtension(languageParser.getValidFileExtensions().get( + 0)); } String filename = zNode.getName() + "." + zNode.getExtension(); save(new File(zNode.getParentFile(), filename), getClassCode(zNode)); @@ -76,8 +97,8 @@ public void save(ZNode zNode) { + zNode.getName().replaceAll("\\W", ".") + (languageParser.requiresSemicolon() ? ";" : "")); } - save(new File(zNode.getParentFile(), languageParser.getPackageFilename()), - zNode.getCodeLines()); + save(new File(zNode.getParentFile(), + languageParser.getPackageFilename()), zNode.getCodeLines()); break; case MODULE: case DEPENDENCY: @@ -87,23 +108,35 @@ public void save(ZNode zNode) { break; case METHOD: saveMethod(zNode); - // TODO: update all line #'s? + updateLineNumbers(zNode); break; } } + private void updateLineNumbers(ZNode methodNode) { + List list = new LinkedList(methodNode.getParentNode() + .getSubmodules()); + boolean pastMethod = false; + final int diff = methodNode.getCodeLineSize() + - methodNode.getOriginalSize(); + + for (ZNode method : list) { + if (methodNode == method) { + pastMethod = true; + continue; + } + if (pastMethod) { + method.setLineNumber(method.getLineNumber() + diff); + } + } + } + /** Overwrite only the method represented by given node. */ private void saveMethod(ZNode zNode) { int n = 0, start, end; try { - if (zNode.getExtension().matches("\\d+-\\d+")) { - String[] split = zNode.getExtension().split("-"); - start = Integer.parseInt(split[0]); - end = Integer.parseInt(split[1]); - } else { - // new method - start = end = Integer.parseInt(zNode.getExtension()); - } + start = zNode.getLineNumber(); + end = start + zNode.getOriginalSize(); final File classFile = zNode.getParentFile(); LineIterator iter = FileUtils.lineIterator(classFile); File temp = File.createTempFile(classFile.getName() + "_z", null); @@ -122,13 +155,10 @@ private void saveMethod(ZNode zNode) { FileUtils.writeLines(temp, asList(line), true); } iter.close(); - zNode.setExtension(start + "-" + (start + zNode.getCodeLineSize())); if (!classFile.delete() || !temp.renameTo(classFile)) { throw new RuntimeException("rename failed!"); } - } catch (NumberFormatException nfe) { - throw new RuntimeException("extension=" + zNode.getExtension()); } catch (IOException e) { throw new RuntimeException("file=" + zNode.getParentFile()); } diff --git a/src/com/adamldavis/z/ZNode.java b/src/com/adamldavis/z/ZNode.java index 05990c4..b293575 100644 --- a/src/com/adamldavis/z/ZNode.java +++ b/src/com/adamldavis/z/ZNode.java @@ -44,6 +44,10 @@ public enum NodeStatus { private final List submodules = new ArrayList(); private long lastModified = System.currentTimeMillis(); + private int lineNumber = 0; // only for things in files, like functions + private ZNode parentNode; // null if no parent + private int originalSize = 0; + public ZNode() { setLocation(new Point2D.Float(0, 0)); } @@ -63,11 +67,18 @@ public ZNode(ZNodeType zNodeType, String name, String code, this.setNodeType(zNodeType); this.setName(name); setCode(code); + this.originalSize = this.code.size(); this.setExtension(extension); this.lastModified = parentFile.lastModified(); this.setParentFile(parentFile); } + public ZNode(ZNodeType zNodeType, String name, String code, int lineNumber, + File parentFile) { + this(zNodeType, name, code, "", parentFile); + this.lineNumber = lineNumber; + } + /** Is code empty? */ public boolean isCodeEmpty() { return code.isEmpty(); @@ -220,4 +231,24 @@ public boolean hasTodo() { return hasTodo; } + public int getLineNumber() { + return lineNumber; + } + + public void setLineNumber(int lineNumber) { + this.lineNumber = lineNumber; + } + + public ZNode getParentNode() { + return parentNode; + } + + public void setParentNode(ZNode parentNode) { + this.parentNode = parentNode; + } + + public int getOriginalSize() { + return originalSize; + } + } diff --git a/src/com/adamldavis/z/api/Editor.java b/src/com/adamldavis/z/api/Editor.java index 1bb4d4a..e7995e9 100644 --- a/src/com/adamldavis/z/api/Editor.java +++ b/src/com/adamldavis/z/api/Editor.java @@ -4,13 +4,15 @@ import javax.swing.JPanel; +import com.adamldavis.z.gui.ColorManager; + public interface Editor { /** Opens a new window with given file. */ JPanel open(File f) throws Exception; - /** Applies the given color mode. */ - void applyColorMode(ColorMode mode); + /** Applies the given color manager. */ + void applyColor(ColorManager colorManager); /** Gets the panel containing the editor. */ JPanel getEditorPanel(); diff --git a/src/com/adamldavis/z/editor/ZCodeEditor.java b/src/com/adamldavis/z/editor/ZCodeEditor.java index 4a0a7b7..4a96f09 100644 --- a/src/com/adamldavis/z/editor/ZCodeEditor.java +++ b/src/com/adamldavis/z/editor/ZCodeEditor.java @@ -12,7 +12,6 @@ import com.adamldavis.z.ZCodeSaver; import com.adamldavis.z.ZNode; import com.adamldavis.z.api.APIFactory; -import com.adamldavis.z.api.ColorMode; public class ZCodeEditor extends EditorAdapter { @@ -30,7 +29,6 @@ public class ZCodeEditor extends EditorAdapter { public ZCodeEditor(ZNode zNode, APIFactory apiFactory) { super(); panel = getEditorPanel(); - applyColorMode(ColorMode.BLACK); setText(apiFactory.getCodeFormatter().format(zNode.getCode())); this.zNode = zNode; this.apiFactory = apiFactory; diff --git a/src/com/adamldavis/z/git/GravatarUtil.java b/src/com/adamldavis/z/git/GravatarUtil.java index d6e29a1..d5cac5b 100644 --- a/src/com/adamldavis/z/git/GravatarUtil.java +++ b/src/com/adamldavis/z/git/GravatarUtil.java @@ -4,43 +4,22 @@ import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; -import java.io.UnsupportedEncodingException; import java.net.MalformedURLException; import java.net.URL; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; import neoe.ne.PicView; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; +import com.adamldavis.z.util.HashUtil; + /** * @author Adam L. Davis * */ public class GravatarUtil { - public static String hex(byte[] array) { - StringBuffer sb = new StringBuffer(); - for (int i = 0; i < array.length; ++i) { - sb.append(Integer.toHexString((array[i] & 0xFF) | 0x100).substring( - 1, 3)); - } - return sb.toString(); - } - - public static String md5Hex(String message) { - try { - MessageDigest md = MessageDigest.getInstance("MD5"); - return hex(md.digest(message.getBytes("CP1252"))); - } catch (NoSuchAlgorithmException e) { - throw new RuntimeException(e); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException(e); - } - } - /** Uses default values of 64 for size and "retro" for deflt. */ public static String getGravatarUrl(String email) { return getGravatarUrl(email, 64, "retro"); @@ -59,8 +38,8 @@ public static String getGravatarUrl(String email) { * @return Just a String URL for the image to get. */ public static String getGravatarUrl(String email, int size, String deflt) { - return "http://www.gravatar.com/avatar/" + md5Hex(email) + ".jpg?s=" - + size + "&d=" + deflt; + return "http://www.gravatar.com/avatar/" + HashUtil.md5Hex(email) + + ".jpg?s=" + size + "&d=" + deflt; } /** diff --git a/src/com/adamldavis/z/gui/ColorManager.java b/src/com/adamldavis/z/gui/ColorManager.java index 7804ba8..7b3fded 100644 --- a/src/com/adamldavis/z/gui/ColorManager.java +++ b/src/com/adamldavis/z/gui/ColorManager.java @@ -18,11 +18,12 @@ * Uses yaml to load colors from color.yml. * * @author Adam L. Davis - * */ public class ColorManager { - static final String filename = "color.yml"; + public static final String COLORS = "colors/"; + + private String filename = COLORS + "colors1.yml"; final Map colors = new HashMap(); @@ -46,6 +47,14 @@ public void load() { } } + public String getFilename() { + return filename; + } + + public void setFilename(String filename) { + this.filename = filename; + } + public static void main(String[] args) { Yaml yaml = new Yaml(); final Map colors = new HashMap(); @@ -60,7 +69,7 @@ public static void main(String[] args) { colors.put(ColorSetting.TASK.name(), "#008500"); colors.put(ColorSetting.SELECTED_TASK.name(), "#67E667"); try { - FileWriter fw = new FileWriter(filename); + FileWriter fw = new FileWriter("color.yml"); yaml.dump(colors, fw); fw.flush(); fw.close(); diff --git a/src/com/adamldavis/z/gui/swing/ZDisplay.java b/src/com/adamldavis/z/gui/swing/ZDisplay.java index df167d4..8827f09 100644 --- a/src/com/adamldavis/z/gui/swing/ZDisplay.java +++ b/src/com/adamldavis/z/gui/swing/ZDisplay.java @@ -59,6 +59,8 @@ public ZDisplay(Z z) { */ @Override protected void paintBuffered(Graphics2D g2d) { + if (z.getZNodes() == null) + return; final List zNodes = new LinkedList(z.getZNodes()); final Point point1 = z.getPoint1(); final Point point2 = z.getPoint2(); @@ -119,7 +121,7 @@ protected void paintBuffered(Graphics2D g2d) { g2d.setStroke(new BasicStroke(2.0f)); for (ZNodeLink link : links) { g2d.setPaint(new GradientPaint(link.getNode1().getLocation(), - hoverColor, link.getNode2().getLocation(), lineColor)); + Color.YELLOW, link.getNode2().getLocation(), lineColor)); g2d.drawLine((int) link.getNode1().getLocation().getX(), (int) link .getNode1().getLocation().getY(), (int) link.getNode2() .getLocation().getX(), (int) link.getNode2().getLocation() @@ -157,4 +159,12 @@ public void showEditorHelp() throws IOException { } } + public void start() { + timer.start(); + } + + public void stop() { + timer.stop(); + } + } diff --git a/src/com/adamldavis/z/gui/swing/ZMenuPainter.java b/src/com/adamldavis/z/gui/swing/ZMenuPainter.java index 6e13eba..5d0cdbb 100644 --- a/src/com/adamldavis/z/gui/swing/ZMenuPainter.java +++ b/src/com/adamldavis/z/gui/swing/ZMenuPainter.java @@ -5,6 +5,8 @@ import java.awt.Font; import java.awt.Graphics2D; +import com.adamldavis.z.gui.ColorManager; +import com.adamldavis.z.gui.ColorSetting; import com.adamldavis.z.gui.Painter; import com.adamldavis.z.gui.ZMenu; @@ -17,6 +19,8 @@ public class ZMenuPainter extends Graphics2DPainter implements Painter { Font font = new Font(Font.SANS_SERIF, Font.BOLD, ZMenu.FONT_SIZE); + ColorManager colorManager = new ColorManager(); + public ZMenuPainter(Graphics2D graphics2d) { super(graphics2d); } @@ -27,11 +31,15 @@ public void paint(Object object) { ZMenu zMenu = (ZMenu) object; if (zMenu.isVisible()) { - graphics2d.setColor(Color.BLACK); + Color back = colorManager.getColorFor(ColorSetting.BACKGROUND); + Color line = colorManager.getColorFor(ColorSetting.LINE); + Color hover = colorManager.getColorFor(ColorSetting.HOVER); + Color text = colorManager.getColorFor(ColorSetting.TEXT); + graphics2d.setColor(back); graphics2d.fillRect(zMenu.getLocation().x, zMenu.getLocation().y, zMenu.getWidth(), zMenu.getHeight()); - graphics2d.setColor(Color.LIGHT_GRAY); + graphics2d.setColor(line); graphics2d.drawRect(zMenu.getLocation().x, zMenu.getLocation().y, zMenu.getWidth(), zMenu.getHeight()); @@ -39,21 +47,24 @@ public void paint(Object object) { ZMenu.Menu hoveredMenu = zMenu.getHoveredMenu(); for (ZMenu.Menu menu : zMenu.getBar().getMenus()) { - if (hoveredMenu != null) { - graphics2d.setColor(Color.WHITE); + if (hoveredMenu == menu) { + graphics2d.setColor(hover); + graphics2d.fillRect(menu.getLocation().x, + menu.getLocation().y - ZMenu.FONT_SIZE, + zMenu.getWidth(), ZMenu.FONT_SIZE); + graphics2d.setColor(back); } else - graphics2d.setColor(Color.LIGHT_GRAY); - + graphics2d.setColor(text); graphics2d.drawString(menu.getName(), menu.getLocation().x, menu.getLocation().y); } if (hoveredMenu != null) { - graphics2d.setColor(Color.BLACK); + graphics2d.setColor(back); int x = hoveredMenu.getLocation().x + zMenu.getWidth(); int y = hoveredMenu.getLocation().y - ZMenu.FONT_SIZE; graphics2d.fillRect(x, y, zMenu.getWidth(), ZMenu.FONT_SIZE * hoveredMenu.getItems().size()); - graphics2d.setColor(Color.WHITE); + graphics2d.setColor(text); graphics2d.drawRect(x, y, zMenu.getWidth(), ZMenu.FONT_SIZE * hoveredMenu.getItems().size()); for (ZMenu.MenuItem item : hoveredMenu.getItems()) { diff --git a/src/com/adamldavis/z/gui/swing/ZNodePainter.java b/src/com/adamldavis/z/gui/swing/ZNodePainter.java index f77a3d4..85e3368 100644 --- a/src/com/adamldavis/z/gui/swing/ZNodePainter.java +++ b/src/com/adamldavis/z/gui/swing/ZNodePainter.java @@ -5,7 +5,6 @@ import java.awt.BasicStroke; import java.awt.Color; import java.awt.Font; -import java.awt.GradientPaint; import java.awt.Graphics2D; import java.awt.Point; @@ -122,9 +121,12 @@ public void draw(ZNode node, Color color) { Point point2 = new Point(x + isize, y + isize / 2); final float codeSize = Math.max(size * 1 / 12, 5); g2d.setFont(new Font(Font.MONOSPACED, Font.PLAIN, round(codeSize))); - g2d.setPaint(new GradientPaint(x, y, hsvColor.darker(), point2.x, - point2.y, Color.BLACK)); - // g2d.setColor(g2d.getBackground()); + Color background = colorManager + .getColorFor(ColorSetting.BACKGROUND); + // g2d.setPaint(new GradientPaint(x, y, colorManager + // .getColorFor(ColorSetting.HOVER), point2.x, point2.y, + // background)); + g2d.setColor(background); int i = 1; for (String line : node.getCodeLines()) { g2d.drawString( diff --git a/src/com/adamldavis/z/java/JavaLanguageParser.java b/src/com/adamldavis/z/java/JavaLanguageParser.java index 255653f..afff8b5 100644 --- a/src/com/adamldavis/z/java/JavaLanguageParser.java +++ b/src/com/adamldavis/z/java/JavaLanguageParser.java @@ -124,7 +124,7 @@ public List getMethods(File file) { } method.replaceCode(code.append(line) .substring(start).toString()); - method.setExtension(methodStart + "-" + lineNumber); + method.setLineNumber(methodStart); inMethod = false; } code.setLength(0); diff --git a/src/com/adamldavis/z/ruby/RubyParser.java b/src/com/adamldavis/z/ruby/RubyParser.java index 47decbc..4ad80f2 100644 --- a/src/com/adamldavis/z/ruby/RubyParser.java +++ b/src/com/adamldavis/z/ruby/RubyParser.java @@ -135,8 +135,8 @@ private void parseRubyLine(String line, List methods, ParserData data) { if (methods != null) { data.code.append(line).append('\n'); methods.add(new ZNode(ZNodeType.METHOD, data.methodName, - data.code.toString(), data.methodStartLine + "-" - + data.n, data.file)); + data.code.toString(), data.methodStartLine, + data.file)); } return; } diff --git a/src/com/adamldavis/z/util/ColorSchemeUtil.java b/src/com/adamldavis/z/util/ColorSchemeUtil.java new file mode 100644 index 0000000..3cebf64 --- /dev/null +++ b/src/com/adamldavis/z/util/ColorSchemeUtil.java @@ -0,0 +1,109 @@ +/** Copyright 2012, Adam L. Davis, all rights reserved. */ +package com.adamldavis.z.util; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.io.FileUtils; +import org.yaml.snakeyaml.Yaml; + +import com.adamldavis.z.gui.ColorSetting; + +/** + * Reads txt file exported from {@linkplain http ://colorschemedesigner.com} and + * saves it as a yaml file for Zeta Code. + * + * @author Adam L. Davis + * + */ +public class ColorSchemeUtil { + + static final char hash = '#'; + static final int hexColorLength = "#123456".length(); + + public static void main(String[] args) { + if (args.length < 1) { + System.out + .println("Usage: java ColorSchemeUtil []"); + return; + } + try { + String out = new File(args[0]).getName(); + if (args.length == 2) { + out = args[1]; + } + convertTextToYml(args[0], out.replace(".txt", ".yml")); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * Reads txt file exported from {@linkplain http ://colorschemedesigner.com} + * and save it as a yaml file for Zeta Code. + * + * @param inFile + * name of file. + * @param filename + * output yml filename. + * @throws IOException + */ + public static void convertTextToYml(String inFile, String filename) + throws IOException { + Yaml yaml = new Yaml(); + final Map colors = new HashMap(); + final String[][] arr = parseSchemeText(inFile); + colors.put(ColorSetting.BACKGROUND.name(), "#1c1d1d"); + colors.put(ColorSetting.LINE.name(), arr[2][4]); + colors.put(ColorSetting.FAIL.name(), arr[0][0]); + colors.put(ColorSetting.OKAY.name(), arr[3][0]); + colors.put(ColorSetting.WARN.name(), arr[1][0]); + colors.put(ColorSetting.TODO.name(), arr[2][0]); + colors.put(ColorSetting.TEXT.name(), arr[1][4]); + colors.put(ColorSetting.HOVER.name(), arr[1][3]); + colors.put(ColorSetting.TASK.name(), arr[3][2]); + colors.put(ColorSetting.SELECTED_TASK.name(), arr[3][4]); + try { + FileWriter fw = new FileWriter(filename); + yaml.dump(colors, fw); + fw.flush(); + fw.close(); + System.out.println("Wrote:" + filename); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * Reads txt file exported from {@linkplain http://colorschemedesigner.com}. + * + * @param inFile + * name of file. + * @return 2 dimensional array (colors*variations). + * @throws IOException + */ + public static String[][] parseSchemeText(String inFile) throws IOException { + List lines = FileUtils.readLines(new File(inFile)); + String[][] arr = new String[4][5]; // colors*variations + int i = -1, j = 0; + + for (String line : lines) { + if (line.startsWith("**")) { + i++; + j = 0; + } else if (i > -1) { + int index = line.indexOf(hash); + if (index > 0) { + arr[i][j] = line.substring(index, index + hexColorLength); + j++; + } + } + } + return arr; + } + +} diff --git a/src/com/adamldavis/z/util/HashUtil.java b/src/com/adamldavis/z/util/HashUtil.java new file mode 100644 index 0000000..f1ebb28 --- /dev/null +++ b/src/com/adamldavis/z/util/HashUtil.java @@ -0,0 +1,53 @@ +/** Copyright 2012, Adam L. Davis, all rights reserved. */ +package com.adamldavis.z.util; + +import java.io.UnsupportedEncodingException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +/** + * @author Adam L. Davis + * + */ +public class HashUtil { + + /** Used by GravatarUtil to emulate md5sum. */ + public static String md5Hex(String message) { + try { + MessageDigest md = MessageDigest.getInstance("MD5"); + return hex(md.digest(message.getBytes("CP1252"))); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } + + public static String hex(byte[] array) { + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < array.length; ++i) { + sb.append(Integer.toHexString((array[i] & 0xFF) | 0x100).substring( + 1, 3)); + } + return sb.toString(); + } + + public static String shaHex(String message) { + try { + MessageDigest md = MessageDigest.getInstance("SHA"); + return hex(md.digest(message.getBytes("UTF-8"))); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } + + public static void main(String[] args) { + System.out.println(shaHex("abc")); + System.out.println(shaHex("cba")); + System.out.println(shaHex("cab")); + System.out.println(shaHex("cab").length()); + } + +}