You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2012/12/06 18:42:18 UTC
[40/52] [partial] ISIS-188: moving framework/ subdirs up to parent
http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/AwtColor.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/AwtColor.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/AwtColor.java
new file mode 100644
index 0000000..5bd5ceb
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/AwtColor.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.isis.viewer.dnd.awt;
+
+import org.apache.isis.runtimes.dflt.runtime.system.context.IsisContext;
+import org.apache.isis.viewer.dnd.drawing.Color;
+import org.apache.isis.viewer.dnd.util.Properties;
+
+public class AwtColor implements Color {
+ public static final AwtColor DEBUG_BASELINE = new AwtColor(java.awt.Color.magenta);
+ public static final AwtColor DEBUG_DRAW_BOUNDS = new AwtColor(java.awt.Color.cyan);
+ public static final AwtColor DEBUG_VIEW_BOUNDS = new AwtColor(java.awt.Color.orange);
+ public static final AwtColor DEBUG_REPAINT_BOUNDS = new AwtColor(java.awt.Color.green);
+ public static final AwtColor DEBUG_BORDER_BOUNDS = new AwtColor(java.awt.Color.pink);
+
+ public static final AwtColor RED = new AwtColor(java.awt.Color.red);
+ public static final AwtColor GREEN = new AwtColor(java.awt.Color.green);
+ public static final AwtColor BLUE = new AwtColor(java.awt.Color.blue);
+ public static final AwtColor BLACK = new AwtColor(java.awt.Color.black);
+ public static final AwtColor WHITE = new AwtColor(java.awt.Color.white);
+ public static final AwtColor GRAY = new AwtColor(java.awt.Color.gray);
+ public static final AwtColor LIGHT_GRAY = new AwtColor(java.awt.Color.lightGray);
+ public static final AwtColor ORANGE = new AwtColor(java.awt.Color.orange);
+ public static final AwtColor YELLOW = new AwtColor(java.awt.Color.yellow);
+
+ static public final AwtColor NULL = new AwtColor(0);
+
+ private static final String PROPERTY_STEM = Properties.PROPERTY_BASE + "color.";
+ private final java.awt.Color color;
+ private String name;
+
+ public AwtColor(final int rgbColor) {
+ this(new java.awt.Color(rgbColor));
+ }
+
+ private AwtColor(final java.awt.Color color) {
+ this.color = color;
+ }
+
+ public AwtColor(final String propertyName, final String defaultColor) {
+ this.name = propertyName;
+ color = IsisContext.getConfiguration().getColor(PROPERTY_STEM + propertyName, java.awt.Color.decode(defaultColor));
+ }
+
+ public AwtColor(final String propertyName, final AwtColor defaultColor) {
+ this.name = propertyName;
+ color = IsisContext.getConfiguration().getColor(PROPERTY_STEM + propertyName, defaultColor.getAwtColor());
+ }
+
+ @Override
+ public Color brighter() {
+ return new AwtColor(color.brighter());
+ }
+
+ @Override
+ public Color darker() {
+ return new AwtColor(color.darker());
+ }
+
+ public java.awt.Color getAwtColor() {
+ return color;
+ }
+
+ @Override
+ public String toString() {
+ return name + " (" + "#" + Integer.toHexString(color.getRGB()) + ")";
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/AwtColorsAndFonts.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/AwtColorsAndFonts.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/AwtColorsAndFonts.java
new file mode 100644
index 0000000..cc05daa
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/AwtColorsAndFonts.java
@@ -0,0 +1,168 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.isis.viewer.dnd.awt;
+
+import java.util.Hashtable;
+
+import org.apache.isis.viewer.dnd.drawing.Color;
+import org.apache.isis.viewer.dnd.drawing.ColorsAndFonts;
+import org.apache.isis.viewer.dnd.drawing.Text;
+import org.apache.isis.viewer.dnd.view.ViewConstants;
+
+public class AwtColorsAndFonts implements ColorsAndFonts {
+ private final Hashtable colors = new Hashtable();
+ private int defaultBaseline;
+ private int defaultFieldHeight;
+ private final Hashtable fonts = new Hashtable();
+
+ @Override
+ public int defaultBaseline() {
+ if (defaultBaseline == 0) {
+ final int iconSize = getText(TEXT_NORMAL).getAscent();
+ defaultBaseline = ViewConstants.VPADDING + iconSize;
+ }
+ return defaultBaseline;
+ }
+
+ @Override
+ public int defaultFieldHeight() {
+ if (defaultFieldHeight == 0) {
+ defaultFieldHeight = getText(TEXT_NORMAL).getTextHeight();
+ }
+ return defaultFieldHeight;
+ }
+
+ @Override
+ public Color getColor(final String name) {
+ Color color = (Color) colors.get(name);
+ if (color == null && name.startsWith(COLOR_WINDOW + ".")) {
+ color = new AwtColor(name, (AwtColor) getColor(COLOR_WINDOW));
+ colors.put(name, color);
+ }
+ return color;
+
+ }
+
+ @Override
+ public Color getColor(final int rgbColor) {
+ return new AwtColor(rgbColor);
+ }
+
+ @Override
+ public Text getText(final String name) {
+ return (Text) fonts.get(name);
+ }
+
+ @Override
+ public void init() {
+ // core color scheme
+ setColor(COLOR_BLACK, "#000000");
+ setColor(COLOR_WHITE, "#ffffff");
+ setColor(COLOR_PRIMARY1, "#666699");
+ setColor(COLOR_PRIMARY2, "#9999cc");
+ setColor(COLOR_PRIMARY3, "#ccccff");
+ setColor(COLOR_SECONDARY1, "#666666");
+ setColor(COLOR_SECONDARY2, "#999999");
+ setColor(COLOR_SECONDARY3, "#cccccc");
+
+ // background colors
+ setColor(COLOR_APPLICATION, "#e0e0e0");
+ setColor(COLOR_WINDOW, getColor(COLOR_WHITE));
+ setColor(COLOR_MENU_VALUE, getColor(COLOR_PRIMARY3)); // "#ccffcc");
+ setColor(COLOR_MENU_CONTENT, getColor(COLOR_PRIMARY3)); // "#ffcccc");
+ setColor(COLOR_MENU_VIEW, getColor(COLOR_SECONDARY3)); // "#ffccff");
+ setColor(COLOR_MENU_WORKSPACE, getColor(COLOR_SECONDARY3)); // "#cccccc");
+
+ // menu colors
+ setColor(COLOR_MENU, getColor(COLOR_BLACK));
+ setColor(COLOR_MENU_DISABLED, getColor(COLOR_SECONDARY1));
+ setColor(COLOR_MENU_REVERSED, getColor(COLOR_WHITE));
+
+ // label colors
+ setColor(COLOR_LABEL_MANDATORY, getColor(COLOR_BLACK));
+ setColor(COLOR_LABEL, getColor(COLOR_SECONDARY1));
+ setColor(COLOR_LABEL_DISABLED, getColor(COLOR_SECONDARY2));
+
+ // state colors
+ setColor(COLOR_IDENTIFIED, getColor(COLOR_PRIMARY1)); // "#0099ff");
+ setColor(COLOR_VALID, "#32CD32");
+ setColor(COLOR_INVALID, "#ee1919");
+ setColor(COLOR_ERROR, "#ee1919");
+ setColor(COLOR_ACTIVE, "#ff0000");
+ setColor(COLOR_OUT_OF_SYNC, "#662200");
+
+ // text colors
+ setColor(COLOR_TEXT_SAVED, getColor(COLOR_SECONDARY1));
+ setColor(COLOR_TEXT_EDIT, getColor(COLOR_PRIMARY1)); // "#009933");
+ setColor(COLOR_TEXT_CURSOR, getColor(COLOR_PRIMARY1));
+ setColor(COLOR_TEXT_HIGHLIGHT, getColor(COLOR_PRIMARY3));
+
+ // debug outline colors
+ setColor(COLOR_DEBUG_BASELINE, AwtColor.DEBUG_BASELINE);
+ setColor(COLOR_DEBUG_BOUNDS_BORDER, AwtColor.DEBUG_BORDER_BOUNDS);
+ setColor(COLOR_DEBUG_BOUNDS_DRAW, AwtColor.DEBUG_DRAW_BOUNDS);
+ setColor(COLOR_DEBUG_BOUNDS_REPAINT, AwtColor.DEBUG_REPAINT_BOUNDS);
+ setColor(COLOR_DEBUG_BOUNDS_VIEW, AwtColor.DEBUG_VIEW_BOUNDS);
+
+ // fonts
+ final String defaultFontFamily = AwtText.defaultFontFamily();
+ final int defaultFontSizeSmall = AwtText.defaultFontSizeSmall();
+ final int defaultFontSizeMedium = AwtText.defaultFontSizeMedium();
+ final int defaultFontSizeLarge = AwtText.defaultFontSizeLarge();
+
+ setText(TEXT_TITLE, defaultFontFamily + "-bold-" + defaultFontSizeLarge);
+
+ setText(TEXT_TITLE_SMALL, defaultFontFamily + "-bold-" + defaultFontSizeMedium);
+ setText(TEXT_NORMAL, defaultFontFamily + "-plain-" + defaultFontSizeMedium);
+ setText(TEXT_CONTROL, defaultFontFamily + "-bold-" + defaultFontSizeMedium);
+ setText(TEXT_STATUS, defaultFontFamily + "--" + defaultFontSizeMedium);
+ setText(TEXT_ICON, defaultFontFamily + "-bold-" + defaultFontSizeMedium);
+ setText(TEXT_MENU, defaultFontFamily + "--" + defaultFontSizeMedium);
+
+ setText(TEXT_LABEL_MANDATORY, defaultFontFamily + "--" + defaultFontSizeSmall);
+ setText(TEXT_LABEL_DISABLED, defaultFontFamily + "--" + defaultFontSizeSmall);
+ setText(TEXT_LABEL, defaultFontFamily + "--" + defaultFontSizeSmall);
+ }
+
+ private void setColor(final String name, final Color defaultColor) {
+ setColor(name, (AwtColor) defaultColor);
+ }
+
+ private void setColor(final String name, final AwtColor defaultColor) {
+ if (getColor(name) == null) {
+ final AwtColor color = new AwtColor(name, defaultColor);
+ colors.put(name, color);
+ }
+ }
+
+ private void setColor(final String name, final String defaultColor) {
+ if (getColor(name) == null) {
+ final AwtColor color = new AwtColor(name, defaultColor);
+ colors.put(name, color);
+ }
+ }
+
+ private void setText(final String name, final String defaultFont) {
+ if (getText(name) == null) {
+ final AwtText font = new AwtText(name, defaultFont);
+ fonts.put(name, font);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/AwtImageFactory.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/AwtImageFactory.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/AwtImageFactory.java
new file mode 100644
index 0000000..27d8c18
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/AwtImageFactory.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.isis.viewer.dnd.awt;
+
+import java.awt.Toolkit;
+import java.awt.image.FilteredImageSource;
+import java.awt.image.RGBImageFilter;
+
+import org.apache.isis.core.runtime.imageloader.TemplateImage;
+import org.apache.isis.core.runtime.imageloader.TemplateImageLoader;
+import org.apache.isis.viewer.dnd.drawing.Color;
+import org.apache.isis.viewer.dnd.drawing.Image;
+import org.apache.isis.viewer.dnd.drawing.ImageFactory;
+import org.apache.isis.viewer.dnd.view.base.AwtImage;
+
+public class AwtImageFactory extends ImageFactory {
+
+ private static class Filter extends RGBImageFilter {
+ @Override
+ public int filterRGB(final int x, final int y, final int rgb) {
+ return 0xFFFFFF - rgb;
+ }
+ }
+
+ private final TemplateImageLoader loader;
+
+ public AwtImageFactory(final TemplateImageLoader imageLoader) {
+ loader = imageLoader;
+ }
+
+ /**
+ * Load an image with the given name.
+ */
+ @Override
+ public Image loadImage(final String path) {
+ final TemplateImage template = templateImage(path);
+ if (template == null) {
+ return null;
+ }
+ return new AwtImage(template.getImage());
+ }
+
+ @Override
+ protected Image loadImage(final String name, final int height, final Color tint) {
+ final TemplateImage template = templateImage(name);
+ if (template == null) {
+ return null;
+ }
+ final java.awt.Image iconImage = template.getIcon(height);
+ if (tint != null) {
+ Toolkit.getDefaultToolkit().createImage(new FilteredImageSource(iconImage.getSource(), new Filter()));
+ }
+ final Image icon = new AwtImage(iconImage);
+ return icon;
+ }
+
+ // ////////////////////////////////////////////////////////////////////
+ // Helpers
+ // ////////////////////////////////////////////////////////////////////
+
+ private TemplateImage templateImage(final String name) {
+ final TemplateImage template = loader.getTemplateImage(name);
+ return template;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/AwtText.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/AwtText.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/AwtText.java
new file mode 100644
index 0000000..e44d913
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/AwtText.java
@@ -0,0 +1,242 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.isis.viewer.dnd.awt;
+
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Frame;
+import java.util.StringTokenizer;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.core.commons.config.IsisConfiguration;
+import org.apache.isis.runtimes.dflt.runtime.system.context.IsisContext;
+import org.apache.isis.viewer.dnd.drawing.ColorsAndFonts;
+import org.apache.isis.viewer.dnd.drawing.Text;
+import org.apache.isis.viewer.dnd.util.Properties;
+
+public class AwtText implements Text {
+ private static final String ASCENT_ADJUST = Properties.PROPERTY_BASE + "ascent-adjust";
+ private static final String FONT_PROPERTY_STEM = Properties.PROPERTY_BASE + "font.";
+ private static final Logger LOG = Logger.getLogger(AwtText.class);
+ private static final String SPACING_PROPERTYSTEM = Properties.PROPERTY_BASE + "spacing.";
+ private final boolean ascentAdjust;
+ private Font font;
+ private final Frame fontMetricsComponent = new Frame();
+ private final int lineSpacing;
+ private int maxCharWidth;
+ private final FontMetrics metrics;
+ private final String propertyName;
+
+ protected AwtText(final String propertyName, final String defaultFont) {
+ final IsisConfiguration cfg = IsisContext.getConfiguration();
+ font = cfg.getFont(FONT_PROPERTY_STEM + propertyName, Font.decode(defaultFont));
+ LOG.info("font " + propertyName + " loaded as " + font);
+
+ this.propertyName = propertyName;
+
+ if (font == null) {
+ font = cfg.getFont(FONT_PROPERTY_STEM + ColorsAndFonts.TEXT_DEFAULT, new Font("SansSerif", Font.PLAIN, 12));
+ }
+
+ metrics = fontMetricsComponent.getFontMetrics(font);
+
+ maxCharWidth = metrics.getMaxAdvance() + 1;
+ if (maxCharWidth == 0) {
+ maxCharWidth = (charWidth('X') + 3);
+ }
+
+ lineSpacing = cfg.getInteger(SPACING_PROPERTYSTEM + propertyName, 0);
+
+ ascentAdjust = cfg.getBoolean(ASCENT_ADJUST, false);
+
+ LOG.debug("font " + propertyName + " height=" + metrics.getHeight() + ", leading=" + metrics.getLeading() + ", ascent=" + metrics.getAscent() + ", descent=" + metrics.getDescent() + ", line spacing=" + lineSpacing);
+ }
+
+ @Override
+ public int charWidth(final char c) {
+ return metrics.charWidth(c);
+ }
+
+ @Override
+ public int getAscent() {
+ return metrics.getAscent() - (ascentAdjust ? metrics.getDescent() : 0);
+ }
+
+ /**
+ * Returns the Font from the AWT used for drawing within the AWT.
+ *
+ * @see Font
+ */
+ public Font getAwtFont() {
+ return font;
+ }
+
+ @Override
+ public int getDescent() {
+ return metrics.getDescent();
+ }
+
+ @Override
+ public int getLineHeight() {
+ return metrics.getHeight() + getLineSpacing();
+ }
+
+ @Override
+ public int getLineSpacing() {
+ return lineSpacing;
+ }
+
+ @Override
+ public String getName() {
+ return propertyName;
+ }
+
+ @Override
+ public int getMidPoint() {
+ return getAscent() / 2;
+ }
+
+ @Override
+ public int getTextHeight() {
+ return metrics.getHeight() - (ascentAdjust ? metrics.getDescent() : 0);
+ }
+
+ @Override
+ public int stringHeight(final String text, final int maxWidth) {
+ int noLines = 0;
+ final StringTokenizer lines = new StringTokenizer(text, "\n\r");
+ while (lines.hasMoreTokens()) {
+ final String line = lines.nextToken();
+ final StringTokenizer words = new StringTokenizer(line, " ");
+ final StringBuffer l = new StringBuffer();
+ int width = 0;
+ while (words.hasMoreTokens()) {
+ final String nextWord = words.nextToken();
+ final int wordWidth = stringWidth(nextWord);
+ width += wordWidth;
+ if (width >= maxWidth) {
+ noLines++;
+ l.setLength(0);
+ width = wordWidth;
+ }
+ l.append(nextWord);
+ l.append(" ");
+ width += stringWidth(" ");
+ }
+ noLines++;
+ }
+ return noLines * getLineHeight();
+ }
+
+ @Override
+ public int stringWidth(final String text, final int maxWidth) {
+ int width = 0;
+ final StringTokenizer lines = new StringTokenizer(text, "\n\r");
+ while (lines.hasMoreTokens()) {
+ final String line = lines.nextToken();
+ final StringTokenizer words = new StringTokenizer(line, " ");
+ final StringBuffer l = new StringBuffer();
+ int lineWidth = 0;
+ while (words.hasMoreTokens()) {
+ final String nextWord = words.nextToken();
+ final int wordWidth = stringWidth(nextWord);
+ lineWidth += wordWidth;
+ if (lineWidth >= maxWidth) {
+ return maxWidth;
+ }
+ if (lineWidth > width) {
+ width = lineWidth;
+ }
+ l.append(nextWord);
+ l.append(" ");
+ lineWidth += stringWidth(" ");
+ }
+ }
+ return width;
+ }
+
+ // DKH: 20060404... yes, this will grow over time, but only used client-side
+ // RCM this is only a temporary solutions to help deal with titles, TODO
+ // move the caching up to the
+ // views/components that use this method
+ private final java.util.Hashtable stringWidthByString = new java.util.Hashtable();
+
+ // DKH 20060404: new implementation that caches
+ @Override
+ public int stringWidth(final String text) {
+ int[] cachedStringWidth = (int[]) stringWidthByString.get(text);
+ if (cachedStringWidth == null) {
+ cachedStringWidth = new int[] { stringWidthInternal(text) };
+ stringWidthByString.put(text, cachedStringWidth);
+ }
+ return cachedStringWidth[0];
+ }
+
+ // DKH 20060404: previously was stringWidth, now cached, see above.
+ private int stringWidthInternal(final String text) {
+ int stringWidth = metrics.stringWidth(text);
+ if (stringWidth > text.length() * maxCharWidth) {
+ LOG.debug("spurious width of string; calculating manually: " + stringWidth + " for " + this + ": " + text);
+ /*
+ * This fixes an intermittent bug in .NET where stringWidth()
+ * returns a ridiculous number is returned for the width.
+ *
+ * TODO don't do this when running Java
+ */
+ stringWidth = 0;
+ for (int i = 0; i < text.length(); i++) {
+ int charWidth = charWidth(text.charAt(i));
+ if (charWidth > maxCharWidth) {
+ LOG.debug("spurious width of character; using max width: " + charWidth + " for " + text.charAt(i));
+ charWidth = maxCharWidth;
+ }
+ stringWidth += charWidth;
+ LOG.debug(i + " " + stringWidth);
+ }
+ }
+ return stringWidth;
+ }
+
+ @Override
+ public String toString() {
+ return font.toString();
+ }
+
+ public static String defaultFontFamily() {
+ final IsisConfiguration cfg = IsisContext.getConfiguration();
+ return cfg.getString(FONT_PROPERTY_STEM + "family", "SansSerif");
+ }
+
+ public static int defaultFontSizeSmall() {
+ final IsisConfiguration cfg = IsisContext.getConfiguration();
+ return cfg.getInteger(FONT_PROPERTY_STEM + "size.small", 10);
+ }
+
+ public static int defaultFontSizeMedium() {
+ final IsisConfiguration cfg = IsisContext.getConfiguration();
+ return cfg.getInteger(FONT_PROPERTY_STEM + "size.medium", 11);
+ }
+
+ public static int defaultFontSizeLarge() {
+ final IsisConfiguration cfg = IsisContext.getConfiguration();
+ return cfg.getInteger(FONT_PROPERTY_STEM + "size.large", 12);
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/AwtToolkit.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/AwtToolkit.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/AwtToolkit.java
new file mode 100644
index 0000000..5d45d27
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/AwtToolkit.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.isis.viewer.dnd.awt;
+
+import org.apache.isis.viewer.dnd.view.Toolkit;
+import org.apache.isis.viewer.dnd.viewer.DefaultContentFactory;
+import org.apache.isis.viewer.dnd.viewer.SkylarkViewFactory;
+import org.apache.isis.viewer.dnd.viewer.basic.LogoBackground;
+
+public class AwtToolkit extends Toolkit {
+ @Override
+ protected void init() {
+ final XViewer v = new XViewer();
+ final XFeedbackManager f = new XFeedbackManager(v);
+ v.setFeedbackManager(f);
+ feedbackManager = f;
+ viewer = v;
+ viewer.setBackground(new LogoBackground());
+ contentFactory = new DefaultContentFactory();
+ viewFactory = new SkylarkViewFactory();
+ colorsAndFonts = new AwtColorsAndFonts();
+
+ colorsAndFonts.init();
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/DebugFrame.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/DebugFrame.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/DebugFrame.java
new file mode 100644
index 0000000..5e87138
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/DebugFrame.java
@@ -0,0 +1,353 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.isis.viewer.dnd.awt;
+
+import java.awt.BorderLayout;
+import java.awt.Button;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Frame;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.Insets;
+import java.awt.Panel;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.TextArea;
+import java.awt.Toolkit;
+import java.awt.event.ActionEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.net.URL;
+import java.util.Vector;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.core.commons.debug.DebugString;
+import org.apache.isis.core.commons.debug.DebuggableWithTitle;
+import org.apache.isis.viewer.dnd.view.debug.DebugOutput;
+
+/**
+ * A specialised frame for displaying the details of an object and its display
+ * mechanisms.
+ */
+public abstract class DebugFrame extends Frame {
+ private static final long serialVersionUID = 1L;
+ private static final Logger LOG = Logger.getLogger(DebugFrame.class);
+ private static Vector<Frame> frames = new Vector<Frame>();
+ private int panel = 0;
+
+ /**
+ * Calls dispose on all the open debug frames
+ *
+ */
+ public static void disposeAll() {
+ final Frame[] f = new Frame[frames.size()];
+
+ for (int i = 0; i < f.length; i++) {
+ f[i] = frames.elementAt(i);
+ }
+
+ for (final Frame element : f) {
+ element.dispose();
+ }
+ }
+
+ private TextArea field;
+ private TabPane tabPane;
+
+ public DebugFrame() {
+ frames.addElement(this);
+
+ addWindowListener(new WindowAdapter() {
+ @Override
+ public void windowClosing(final WindowEvent e) {
+ closeDialog();
+ }
+ });
+
+ final URL url = DebugFrame.class.getResource("/" + "images/debug-log.gif");
+ if (url != null) {
+ final Image image = Toolkit.getDefaultToolkit().getImage(url);
+ if (image != null) {
+ setIconImage(image);
+ }
+ }
+
+ setLayout(new BorderLayout(7, 7));
+ final Panel tabPane = createTabPane();
+ add(tabPane);
+ }
+
+ private Panel createTabPane() {
+ tabPane = new TabPane();
+ tabPane.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseClicked(final MouseEvent e) {
+ final Point point = e.getPoint();
+ panel = tabPane.select(point);
+
+ showDebugForPane();
+ }
+ });
+
+ tabPane.setLayout(new BorderLayout(7, 7));
+
+ final TextArea textArea = new TextArea("", 60, 110, TextArea.SCROLLBARS_BOTH);
+ textArea.setForeground(Color.black);
+ textArea.setEditable(false);
+ // Font font = Isis.getConfiguration().getFont("isis.debug.font", new
+ // Font("Monospaced", Font.PLAIN, 10));
+ final Font font = new Font("Monospaced", Font.PLAIN, 11);
+ textArea.setFont(font);
+ tabPane.add("Center", textArea);
+ field = textArea;
+
+ final Panel buttons = new Panel();
+ buttons.setLayout(new FlowLayout());
+ tabPane.add(buttons, BorderLayout.SOUTH);
+
+ // add buttons
+ Button b = new java.awt.Button("Refresh");
+ b.setFont(font);
+
+ buttons.add(b);
+ b.addActionListener(new java.awt.event.ActionListener() {
+ @Override
+ public void actionPerformed(final ActionEvent e) {
+ showDebugForPane();
+ }
+ });
+
+ b = new java.awt.Button("Print...");
+ b.setFont(font);
+
+ buttons.add(b);
+ b.addActionListener(new java.awt.event.ActionListener() {
+ @Override
+ public void actionPerformed(final ActionEvent e) {
+ DebugOutput.print("Debug " + tabPane.getName(), field.getText());
+ }
+ });
+
+ b = new java.awt.Button("Save...");
+ b.setFont(font);
+
+ buttons.add(b);
+ b.addActionListener(new java.awt.event.ActionListener() {
+ @Override
+ public void actionPerformed(final ActionEvent e) {
+ DebugOutput.saveToFile("Save details", "Debug " + tabPane.getName(), field.getText());
+ }
+ });
+
+ b = new java.awt.Button("Copy");
+ b.setFont(font);
+
+ buttons.add(b);
+ b.addActionListener(new java.awt.event.ActionListener() {
+ @Override
+ public void actionPerformed(final ActionEvent e) {
+ DebugOutput.saveToClipboard(field.getText());
+ }
+ });
+
+ b = new java.awt.Button("Close");
+ b.setFont(font);
+
+ buttons.add(b);
+ b.addActionListener(new java.awt.event.ActionListener() {
+ @Override
+ public void actionPerformed(final ActionEvent e) {
+ closeDialog();
+ }
+ });
+
+ return tabPane;
+ }
+
+ @Override
+ public Insets getInsets() {
+ final Insets insets = super.getInsets();
+ insets.left += 10;
+ insets.right += 10;
+ insets.top += 10;
+ insets.bottom += 10;
+ return insets;
+ }
+
+ private void closeDialog() {
+ dialogClosing();
+ // hide();
+ dispose();
+ }
+
+ public void dialogClosing() {
+ }
+
+ @Override
+ public void dispose() {
+ LOG.debug("dispose...");
+ tabPane.removeAll();
+ frames.removeElement(this);
+ super.dispose();
+ LOG.debug("...disposed");
+ }
+
+ protected abstract DebuggableWithTitle[] getInfo();
+
+ /**
+ * show the frame at the specified coordinates
+ */
+ public void show(final int x, final int y) {
+ /*
+ * WARNING - When refresh button is pressed it is in the AWT thread; if
+ * the repository is thread based then the wrong set of components will
+ * be used giving strange results, particularly in the object persistor.
+ */
+ // TODO run in correct thread
+ refresh();
+
+ pack();
+ limitBounds(x, y);
+ setVisible(true);
+ }
+
+ private void refresh() {
+ final DebuggableWithTitle[] infos = getInfo();
+ final DebuggableWithTitle info = infos[panel];
+ if (info != null) {
+ setTitle(info.debugTitle());
+ final DebugString str = new DebugString();
+ info.debugData(str);
+ field.setText(str.toString());
+ field.setCaretPosition(0);
+ }
+ }
+
+ public void showDebugForPane() {
+ refresh();
+ }
+
+ private void limitBounds(final int xLimit, final int yLimit) {
+ final Dimension screenSize = getToolkit().getScreenSize();
+ final int maxWidth = screenSize.width - 50;
+ final int maxHeight = screenSize.height - 50;
+
+ int width = getSize().width;
+ int height = getSize().height;
+
+ int x = xLimit;
+ if (x + width > maxWidth) {
+ x = 0;
+ if (x + width > maxWidth) {
+ width = maxWidth;
+ }
+ }
+
+ int y = yLimit;
+ if (y + height > maxHeight) {
+ y = 0;
+ if (y + height > maxHeight) {
+ height = maxHeight;
+ }
+ }
+
+ setSize(width, height);
+ setLocation(x, y);
+ }
+
+ private class TabPane extends Panel {
+ private static final long serialVersionUID = 1L;
+ private Rectangle[] tabs;
+ private int panel = 0;
+
+ public int select(final Point point) {
+ for (int i = 0; i < tabs.length; i++) {
+ if (tabs[i] != null && tabs[i].contains(point)) {
+ panel = i;
+ repaint();
+ break;
+ }
+ }
+ return panel;
+ }
+
+ @Override
+ public Insets getInsets() {
+ final Insets insets = super.getInsets();
+ insets.left += 10;
+ insets.right += 10;
+ insets.top += 30;
+ insets.bottom += 10;
+ return insets;
+ }
+
+ @Override
+ public void paint(final Graphics g) {
+ final DebuggableWithTitle[] info = getInfo();
+
+ if (info != null) {
+ if (tabs == null) {
+ tabs = new Rectangle[getInfo().length];
+ }
+ final Dimension size = getSize();
+ g.setColor(Color.gray);
+ g.drawRect(0, 20, size.width - 1, size.height - 21);
+
+ FontMetrics fm;
+ fm = g.getFontMetrics();
+ int offset = 0;
+ final int maxWidth = info.length == 0 ? size.width : size.width / info.length - 1;
+ for (int i = 0; i < info.length; i++) {
+ String title = info[i].debugTitle();
+ title = title == null ? info[i].getClass().getName() : title;
+ final int width = Math.min(maxWidth, fm.stringWidth(title) + 20);
+
+ tabs[i] = new Rectangle(offset, 0, width, 20);
+ g.setColor(Color.gray);
+ g.drawRect(offset + 0, 0, width, 20);
+ if (i == panel) {
+ g.setColor(Color.white);
+ g.fillRect(offset + 1, 1, width - 1, 20);
+ // g.drawLine(offset + 1, 20, offset + width, 20);
+ g.setColor(Color.black);
+ } else {
+ g.setColor(Color.lightGray);
+ g.fillRect(offset + 1, 1, width - 1, 20 - 1);
+ g.setColor(Color.gray);
+ }
+
+ g.drawString(title, offset + 9, 20 - 5);
+
+ offset += width;
+ }
+ g.setColor(Color.white);
+ g.fillRect(offset + 1, 1, size.width - offset, 20 - 1);
+ }
+ }
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/DebugOptions.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/DebugOptions.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/DebugOptions.java
new file mode 100644
index 0000000..56df754
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/DebugOptions.java
@@ -0,0 +1,158 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.isis.viewer.dnd.awt;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+
+import org.apache.isis.core.commons.debug.DebugBuilder;
+import org.apache.isis.core.commons.debug.DebuggableWithTitle;
+import org.apache.isis.core.metamodel.spec.ActionType;
+import org.apache.isis.core.runtime.sysout.SystemPrinter;
+import org.apache.isis.runtimes.dflt.runtime.system.context.IsisContext;
+import org.apache.isis.viewer.dnd.drawing.Location;
+import org.apache.isis.viewer.dnd.view.MenuOptions;
+import org.apache.isis.viewer.dnd.view.Toolkit;
+import org.apache.isis.viewer.dnd.view.UserActionSet;
+import org.apache.isis.viewer.dnd.view.View;
+import org.apache.isis.viewer.dnd.view.Workspace;
+import org.apache.isis.viewer.dnd.view.option.UserActionAbstract;
+
+public class DebugOptions implements MenuOptions {
+ private final XViewer viewer;
+
+ public DebugOptions(final XViewer viewer) {
+ this.viewer = viewer;
+ }
+
+ @Override
+ public void menuOptions(final UserActionSet options) {
+ final String showExplorationMenu = "Always show exploration menu " + (viewer.showExplorationMenuByDefault ? "off" : "on");
+ options.add(new UserActionAbstract(showExplorationMenu, ActionType.DEBUG) {
+ @Override
+ public void execute(final Workspace workspace, final View view, final Location at) {
+ viewer.showExplorationMenuByDefault = !viewer.showExplorationMenuByDefault;
+ view.markDamaged();
+ }
+ });
+
+ final String repaint = "Show painting area " + (viewer.showRepaintArea ? "off" : "on");
+ options.add(new UserActionAbstract(repaint, ActionType.DEBUG) {
+ @Override
+ public void execute(final Workspace workspace, final View view, final Location at) {
+ viewer.showRepaintArea = !viewer.showRepaintArea;
+ view.markDamaged();
+ }
+ });
+
+ final String debug = "Debug graphics " + (Toolkit.debug ? "off" : "on");
+ options.add(new UserActionAbstract(debug, ActionType.DEBUG) {
+ @Override
+ public void execute(final Workspace workspace, final View view, final Location at) {
+ Toolkit.debug = !Toolkit.debug;
+ view.markDamaged();
+ }
+ });
+
+ final String action = viewer.isShowingMouseSpy() ? "Hide" : "Show";
+ options.add(new UserActionAbstract(action + " mouse spy", ActionType.DEBUG) {
+ @Override
+ public void execute(final Workspace workspace, final View view, final Location at) {
+ viewer.setShowMouseSpy(!viewer.isShowingMouseSpy());
+ }
+ });
+
+ // I've commented this out because in the new design we should close the
+ // ExecutionContext
+ // and then re-login.
+ // options.add(new AbstractUserAction("Restart object loader/persistor",
+ // UserAction.DEBUG) {
+ // @Override
+ // public void execute(final Workspace workspace, final View view, final
+ // Location at) {
+ // IsisContext.getObjectPersistor().reset();
+ // }
+ // });
+
+ options.add(new UserActionAbstract("Diagnostics...", ActionType.DEBUG) {
+ @Override
+ public void execute(final Workspace workspace, final View view, final Location at) {
+ final InfoDebugFrame f = new InfoDebugFrame();
+ final DebuggableWithTitle info = new DebuggableWithTitle() {
+
+ @Override
+ public void debugData(final DebugBuilder debug) {
+ final ByteArrayOutputStream out2 = new ByteArrayOutputStream();
+ final PrintStream out = new PrintStream(out2);
+ new SystemPrinter(out).printDiagnostics();
+ debug.append(out2.toString());
+ }
+
+ @Override
+ public String debugTitle() {
+ return "Diagnostics";
+ }
+
+ };
+ f.setInfo(info);
+ f.show(at.getX() + 50, workspace.getBounds().getY() + 6);
+ }
+ });
+
+ options.add(new UserActionAbstract("Debug system...", ActionType.DEBUG) {
+ @Override
+ public void execute(final Workspace workspace, final View view, final Location at) {
+ final InfoDebugFrame f = new InfoDebugFrame();
+ final DebuggableWithTitle[] contextInfo = IsisContext.debugSystem();
+ f.setInfo(contextInfo);
+ f.show(at.getX() + 50, workspace.getBounds().getY() + 6);
+ }
+ });
+
+ options.add(new UserActionAbstract("Debug session...", ActionType.DEBUG) {
+ @Override
+ public void execute(final Workspace workspace, final View view, final Location at) {
+ final InfoDebugFrame f = new InfoDebugFrame();
+ final DebuggableWithTitle[] contextInfo = IsisContext.debugSession();
+ f.setInfo(contextInfo);
+ f.show(at.getX() + 50, workspace.getBounds().getY() + 6);
+ }
+ });
+
+ options.add(new UserActionAbstract("Debug viewer...", ActionType.DEBUG) {
+ @Override
+ public void execute(final Workspace workspace, final View view, final Location at) {
+ final InfoDebugFrame f = new InfoDebugFrame();
+ f.setInfo(new DebuggableWithTitle[] { Toolkit.getViewFactory(), viewer.updateNotifier });
+ f.show(at.getX() + 50, workspace.getBounds().getY() + 6);
+ }
+ });
+
+ options.add(new UserActionAbstract("Debug overlay...", ActionType.DEBUG) {
+ @Override
+ public void execute(final Workspace workspace, final View view, final Location at) {
+ final DebugFrame f = new OverlayDebugFrame(viewer);
+ f.show(at.getX() + 50, workspace.getBounds().getY() + 6);
+ }
+ });
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/InfoDebugFrame.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/InfoDebugFrame.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/InfoDebugFrame.java
new file mode 100644
index 0000000..bfc55fd
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/InfoDebugFrame.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.isis.viewer.dnd.awt;
+
+import org.apache.isis.core.commons.debug.DebuggableWithTitle;
+
+public class InfoDebugFrame extends DebugFrame {
+ private static final long serialVersionUID = 1L;
+ private DebuggableWithTitle[] info;
+
+ @Override
+ protected DebuggableWithTitle[] getInfo() {
+ return info;
+ }
+
+ /**
+ * set the display strategy to use to display the information.
+ */
+ public void setInfo(final DebuggableWithTitle info) {
+ this.info = new DebuggableWithTitle[] { info };
+ }
+
+ /**
+ * set the display strategies to use to display the information.
+ */
+ public void setInfo(final DebuggableWithTitle[] info) {
+ this.info = info;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/InteractionHandler.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/InteractionHandler.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/InteractionHandler.java
new file mode 100644
index 0000000..5b584a4
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/InteractionHandler.java
@@ -0,0 +1,503 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.isis.viewer.dnd.awt;
+
+import java.awt.Point;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.viewer.dnd.drawing.Location;
+import org.apache.isis.viewer.dnd.interaction.ClickImpl;
+import org.apache.isis.viewer.dnd.interaction.ContentDragImpl;
+import org.apache.isis.viewer.dnd.interaction.DragStartImpl;
+import org.apache.isis.viewer.dnd.view.Click;
+import org.apache.isis.viewer.dnd.view.ContentDrag;
+import org.apache.isis.viewer.dnd.view.DragEvent;
+import org.apache.isis.viewer.dnd.view.InteractionSpy;
+import org.apache.isis.viewer.dnd.view.View;
+import org.apache.isis.viewer.dnd.view.ViewAreaType;
+import org.apache.isis.viewer.dnd.view.base.AbstractView;
+import org.apache.isis.viewer.dnd.view.content.NullContent;
+
+public class InteractionHandler implements MouseMotionListener, MouseListener, KeyListener {
+ private static final Logger LOG = Logger.getLogger(InteractionHandler.class);
+ private final static int THRESHOLD = 7;
+ private boolean canDrag;
+ /*
+ * The location within the frame where the mouse button was pressed down.
+ */
+ private Location downAt;
+ private DragEvent drag;
+ private final KeyboardManager keyboardManager;
+ private View identifiedView;
+ private final InteractionSpy spy;
+ private final XViewer viewer;
+ private KeyEvent lastTyped;
+ private View draggedView;
+ private final XFeedbackManager feedbackManager;
+
+ public InteractionHandler(final XViewer viewer, final XFeedbackManager feedbackManager, final KeyboardManager keyboardManager, final InteractionSpy spy) {
+ this.viewer = viewer;
+ this.feedbackManager = feedbackManager;
+ this.spy = spy;
+ this.keyboardManager = keyboardManager;
+ }
+
+ private void drag(final MouseEvent me) {
+ final Location location = createLocation(me.getPoint());
+ spy.addAction("Mouse dragged " + location);
+ final View target = viewer.identifyView(new Location(location), false);
+ drag.drag(target, location, me.getModifiers());
+ }
+
+ private Location createLocation(final Point point) {
+ return new Location(point.x, point.y);
+ }
+
+ private void dragStart(final MouseEvent me) {
+ if (!isOverThreshold(downAt, me.getPoint())) {
+ return;
+ }
+
+ spy.addAction("Drag start at " + downAt);
+ drag = viewer.dragStart(new DragStartImpl(downAt, me.getModifiers()));
+
+ if (drag == null) {
+ spy.addAction("drag start ignored");
+ canDrag = false;
+ } else {
+ spy.addAction("drag start " + drag);
+ final View overlay = drag.getOverlay();
+ if (overlay != null) {
+ viewer.setOverlayView(overlay);
+ }
+ final View target = viewer.identifyView(createLocation(me.getPoint()), false);
+ drag.drag(target, createLocation(me.getPoint()), me.getModifiers());
+ }
+ identifiedView = null;
+ }
+
+ /**
+ * Returns true when the point is outside the area around the downAt
+ * location
+ */
+ private boolean isOverThreshold(final Location pressed, final Point dragged) {
+ final int xDown = pressed.getX();
+ final int yDown = pressed.getY();
+ final int x = dragged.x;
+ final int y = dragged.y;
+
+ return x > xDown + THRESHOLD || x < xDown - THRESHOLD || y > yDown + THRESHOLD || y < yDown - THRESHOLD;
+ }
+
+ /**
+ * Listener for key presses. Cancels popup and drags, and forwards key
+ * presses to the view that has the keyboard focus.
+ *
+ * @see java.awt.event.KeyListener#keyPressed(KeyEvent)
+ */
+ @Override
+ public void keyPressed(final KeyEvent ke) {
+ if (isBusy(identifiedView)) {
+ return;
+ }
+
+ lastTyped = null;
+ try {
+ if (ke.getKeyCode() == KeyEvent.VK_ESCAPE && drag != null) {
+ if (drag != null) {
+ drag.cancel(viewer);
+ drag = null;
+ }
+ viewer.clearAction();
+ } else if (ke.getKeyCode() == KeyEvent.VK_F5) {
+ draggedView = identifiedView;
+ } else if (draggedView != null && ke.getKeyCode() == KeyEvent.VK_F6) {
+ final ContentDrag content = new ContentDragImpl(draggedView, new Location(), new AbstractView(new NullContent()) {
+ });
+ if (identifiedView != null) {
+ identifiedView.drop(content);
+ }
+
+ draggedView = null;
+ } else {
+ keyboardManager.pressed(ke.getKeyCode(), ke.getModifiers());
+ }
+ // ke.consume();
+
+ redraw();
+ } catch (final Exception e) {
+ interactionException("keyPressed", e);
+ }
+ }
+
+ /**
+ * Listener for key releases and forward them to the view that has the
+ * keyboard focus.
+ *
+ * @see java.awt.event.KeyListener#keyReleased(KeyEvent)
+ */
+ @Override
+ public void keyReleased(final KeyEvent ke) {
+ if (isBusy(identifiedView)) {
+ return;
+ }
+ // LOG.debug("key " + KeyEvent.getKeyText(ke.getKeyCode()) +
+ // " released\n");
+
+ try {
+ if (lastTyped == null && ke.getKeyCode() != KeyEvent.VK_SHIFT && ke.getKeyCode() != KeyEvent.VK_ALT && ke.getKeyCode() != KeyEvent.VK_CONTROL) {
+ if (ke.getKeyCode() >= KeyEvent.VK_0 && ke.getKeyCode() <= KeyEvent.VK_DIVIDE) {
+ LOG.error("no type event for '" + KeyEvent.getKeyText(ke.getKeyCode()) + "': " + ke);
+ }
+ }
+
+ keyboardManager.released(ke.getKeyCode(), ke.getModifiers());
+ ke.consume();
+ redraw();
+ } catch (final Exception e) {
+ interactionException("keyReleased", e);
+ }
+
+ }
+
+ /**
+ * Listener for key press, and subsequent release, and forward it as one
+ * event to the view that has the keyboard focus.
+ *
+ * @see java.awt.event.KeyListener#keyTyped(KeyEvent)
+ */
+ @Override
+ public void keyTyped(final KeyEvent ke) {
+ if (isBusy(identifiedView)) {
+ return;
+ }
+
+ final char keyChar = ke.getKeyChar();
+ if (!Character.isISOControl(keyChar)) {
+ // ignoring control keys and the delete key
+ // LOG.debug("typed '" + keyChar + "': " + ke);
+ // LOG.debug("typed " + (int) keyChar);
+ keyboardManager.typed(keyChar);
+ ke.consume();
+ lastTyped = ke;
+ redraw();
+ }
+ }
+
+ private void interactionException(final String action, final Exception e) {
+ LOG.error("error during user interaction: " + action, e);
+ feedbackManager.showException(e);
+ }
+
+ /**
+ * Responds to mouse click events by calling <code>firstClick</code>,
+ * <code>secondClick</code>, and <code>thirdClick</code> on the view that
+ * the mouse is over. Ignored if the mouse is not over a view.
+ *
+ * @see java.awt.event.MouseListener#mouseClicked(MouseEvent)
+ */
+ @Override
+ public void mouseClicked(final MouseEvent me) {
+ if (isBusy(identifiedView)) {
+ return;
+ }
+ try {
+ final Click click = new ClickImpl(downAt, me.getModifiers());
+ spy.addAction("Mouse clicked " + click.getLocation());
+ if (click.button3() && identifiedView != null) {
+ // ignore popup trigger - dealt with by mousePressed or
+ // mouseReleased (depending on platform)
+ } else if (viewer.isOverlayAvailable()) {
+ overlayClick(click);
+ // } else if (click.button3() && identifiedView != null) {
+ // fireMenuPopup(click);
+ } else {
+ fireClick(click, me.getClickCount());
+ }
+ redraw();
+ } catch (final Exception e) {
+ interactionException("mouseClicked", e);
+ }
+ }
+
+ private void overlayClick(final Click click) {
+ final View overlayView = viewer.getOverlayView();
+ if (overlayView == identifiedView || (identifiedView != null && identifiedView.getParent() != null && overlayView == identifiedView.getParent())) {
+ viewer.firstClick(click);
+ } else {
+ viewer.clearAction();
+ }
+ }
+
+ private void fireMenuPopup(final Click click) {
+ if (identifiedView != null) {
+ spy.addAction(" popup " + downAt + " over " + identifiedView);
+
+ boolean forView = viewer.viewAreaType(new Location(click.getLocation())) == ViewAreaType.VIEW;
+ forView = click.isAlt() ^ forView;
+ final boolean includeExploration = click.isCtrl();
+ final boolean includeDebug = click.isShift();
+ final Location at = click.getLocation();
+ at.move(-14, -10);
+ viewer.popupMenu(identifiedView, at, forView, includeExploration, includeDebug);
+ }
+ }
+
+ private void fireClick(final Click click, final int clickCount) {
+ viewer.setKeyboardFocus(identifiedView);
+
+ switch (clickCount) {
+ case 1:
+ viewer.firstClick(click);
+ break;
+
+ case 2:
+ viewer.secondClick(click);
+ break;
+
+ case 3:
+ viewer.thirdClick(click);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /**
+ * Responds to mouse dragged according to the button used. If the left
+ * button then identified view is moved.
+ *
+ * @see java.awt.event.MouseMotionListener#mouseDragged(MouseEvent)
+ */
+ @Override
+ public void mouseDragged(final MouseEvent me) {
+ if (isBusy(identifiedView)) {
+ return;
+ }
+
+ try {
+ viewer.translate(me);
+
+ final Location location = createLocation(me.getPoint());
+ spy.setLocationInViewer(location);
+
+ if (canDrag) {
+ // checked to ensure that dragging over a view doesn't start a
+ // drag - it should only start when already over a view.
+
+ spy.reset();
+ // viewer.translate(me);
+ if (drag == null) {
+ // no drag in progress yet
+ dragStart(me);
+ redraw();
+ } else {
+ drag(me);
+ redraw();
+ }
+ }
+ } catch (final Exception e) {
+ interactionException("mouseDragged", e);
+ }
+
+ }
+
+ /**
+ * event ignored
+ *
+ * @see java.awt.event.MouseListener#mouseEntered(MouseEvent)
+ */
+ @Override
+ public void mouseEntered(final MouseEvent arg0) {
+ }
+
+ /**
+ * event ignored
+ *
+ * @see java.awt.event.MouseListener#mouseExited(MouseEvent)
+ */
+ @Override
+ public void mouseExited(final MouseEvent arg0) {
+ }
+
+ /**
+ * responds to mouse moved event by setting the view found underneath the
+ * mouse as the idetified view. Views normally respond by changing the
+ * colour of themselves so they are visual distinct and hence shows itself
+ * as special compared to the rest.
+ *
+ * @see java.awt.event.MouseMotionListener#mouseMoved(MouseEvent)
+ */
+ @Override
+ public void mouseMoved(final MouseEvent me) {
+ try {
+ if (drag == null) {
+ spy.reset();
+ viewer.translate(me);
+ final Location location = createLocation(me.getPoint());
+ spy.setLocationInViewer(location);
+
+ final View overView = viewer.identifyView(new Location(location), true);
+ spy.setOver(overView);
+
+ spy.addAction("moved " + location);
+
+ if (overView != null) {
+ if (overView != identifiedView) {
+ if (identifiedView != null) {
+ spy.addAction("exited " + identifiedView);
+ identifiedView.exited();
+ }
+
+ if (overView != null) {
+ spy.addAction("entered " + overView);
+ overView.entered();
+ }
+
+ redraw();
+ feedbackManager.showBusyState(overView);
+ }
+ identifiedView = overView;
+
+ spy.addTrace("--> mouse moved");
+ viewer.mouseMoved(location);
+ spy.addTrace(overView, " mouse location", location);
+ if ((me.getModifiers() & InputEvent.ALT_MASK) > 0 && overView.getContent() != null) {
+ final ObjectAdapter object = overView.getContent().getAdapter();
+ final ViewAreaType area = overView.viewAreaType(location);
+ feedbackManager.setViewDetail("Over " + location + " [" + area + "] " + object);
+ }
+
+ redraw();
+ }
+ }
+ } catch (final Exception e) {
+ interactionException("mouseMoved", e);
+ }
+
+ }
+
+ private boolean isBusy(final View view) {
+ return feedbackManager != null && feedbackManager.isBusy(view);
+ }
+
+ /**
+ * Responds to the mouse pressed event (with the left button pressed) by
+ * initiating a drag. This sets up the <code>View</code>'s dragging state to
+ * the view that the mouse was over when the button was pressed.
+ *
+ * @see java.awt.event.MouseListener#mousePressed(MouseEvent)
+ */
+ @Override
+ public void mousePressed(final MouseEvent me) {
+ try {
+ if (isBusy(identifiedView)) {
+ return;
+ }
+
+ spy.reset();
+ viewer.translate(me);
+
+ downAt = createLocation(me.getPoint());
+ spy.setDownAt(downAt);
+
+ final Location location = createLocation(me.getPoint());
+ spy.setLocationInViewer(location);
+
+ final View overView = viewer.identifyView(new Location(location), true);
+ spy.setOver(overView);
+ spy.addAction("Mouse pressed " + location);
+ drag = null;
+
+ final Click click = new ClickImpl(downAt, me.getModifiers());
+ if (me.isPopupTrigger()) {
+ if (overView != null) {
+ fireMenuPopup(click);
+ }
+ } else {
+ viewer.mouseDown(click);
+ // drag should not be valid after double/triple click
+ canDrag = overView != null && me.getClickCount() == 1;
+ identifiedView = overView;
+ }
+ redraw();
+ } catch (final Exception e) {
+ interactionException("mousePressed", e);
+ }
+
+ }
+
+ /**
+ * Responds to the mouse released event (with the left button pressed) by
+ * telling the identified view (the drop zone) that the dragged object is
+ * being dropped on it (via the views <code>drop</code> method). If the drop
+ * takes place outside of all of the other views then the
+ * <code>workspaceDrop</code> method is called instead to indicate a drop
+ * onto the workspace.
+ *
+ * @see java.awt.event.MouseListener#mouseReleased(MouseEvent)
+ */
+ @Override
+ public void mouseReleased(final MouseEvent me) {
+ if (isBusy(identifiedView) || downAt == null) {
+ return;
+ }
+
+ try {
+ if (drag != null) {
+ mouseDragged(me);
+
+ final Location location = createLocation(me.getPoint());
+ final View target = viewer.identifyView(new Location(location), false);
+ drag.drag(target, location, me.getModifiers());
+ // viewer.clearStatus();
+ drag.end(viewer);
+ redraw();
+
+ drag = null;
+ }
+
+ final Click click = new ClickImpl(downAt, me.getModifiers());
+ if (me.isPopupTrigger()) {
+ if (identifiedView != null) {
+ fireMenuPopup(click);
+ }
+ } else {
+ viewer.mouseUp(click);
+ }
+ redraw();
+ } catch (final Exception e) {
+ interactionException("mouseReleased", e);
+ }
+ }
+
+ private void redraw() {
+ viewer.scheduleRepaint();
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/KeyboardManager.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/KeyboardManager.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/KeyboardManager.java
new file mode 100644
index 0000000..05b35c5
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/KeyboardManager.java
@@ -0,0 +1,228 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.isis.viewer.dnd.awt;
+
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.core.commons.exceptions.IsisException;
+import org.apache.isis.viewer.dnd.drawing.Location;
+import org.apache.isis.viewer.dnd.interaction.KeyboardActionImpl;
+import org.apache.isis.viewer.dnd.view.FocusManager;
+import org.apache.isis.viewer.dnd.view.KeyboardAction;
+import org.apache.isis.viewer.dnd.view.View;
+
+public class KeyboardManager {
+ private static final Logger LOG = Logger.getLogger(KeyboardManager.class);
+ private final XViewer viewer;
+ private FocusManager focusManager;
+
+ public KeyboardManager(final XViewer viewer) {
+ this.viewer = viewer;
+ }
+
+ private View getFocus() {
+ return focusManager == null ? null : focusManager.getFocus();
+ // View focus = viewer.getFocus();
+ // return focus == null ? null : focus.getView();
+ }
+
+ /*
+ * At the moment, as a fudge, the text field is calling its parent's
+ * keyPressed method for enter presses.
+ */
+ public void pressed(final int keyCode, final int modifiers) {
+ if (ignoreKey(keyCode)) {
+ return;
+ }
+ LOG.debug("key " + KeyEvent.getKeyModifiersText(modifiers) + " '" + KeyEvent.getKeyText(keyCode) + "' pressed");
+
+ final KeyboardAction keyboardAction = new KeyboardActionImpl(keyCode, modifiers);
+
+ if (viewer.isOverlayAvailable()) {
+ viewer.getOverlayView().keyPressed(keyboardAction);
+ if (!keyboardAction.isConsumed() && keyCode == KeyEvent.VK_F1) {
+ viewer.openHelp(viewer.getOverlayView());
+ // help(viewer.getOverlayView());
+ }
+ return;
+ }
+
+ final View keyboardFocus = getFocus();
+ if (keyboardFocus == null) {
+ // throw new ObjectAdapterRuntimeException("No focus set");
+ LOG.debug("No focus set");
+ return;
+ }
+
+ keyboardFocus.keyPressed(keyboardAction);
+
+ if (keyboardAction.isConsumed()) {
+ return;
+ }
+
+ if ((modifiers & InputEvent.SHIFT_MASK) == InputEvent.SHIFT_MASK && keyCode == KeyEvent.VK_F10) {
+ final Location location = keyboardFocus.getAbsoluteLocation();
+ location.add(20, 14);
+ viewer.popupMenu(keyboardFocus, location, true, false, false);
+ return;
+ }
+
+ // this should really check the modifiers to ensure there are none in
+ // use.
+ if (keyCode == KeyEvent.VK_F10) {
+ final Location location = keyboardFocus.getAbsoluteLocation();
+ location.add(20, 14);
+ viewer.popupMenu(keyboardFocus, location, false, false, false);
+ return;
+ }
+ /*
+ * if(keyCode == KeyEvent.VK_ENTER) { //viewer.firstClick(new
+ * Click(keyboardFocus, keyboardFocus.getLocation(), modifiers));
+ * Location location = keyboardFocus.getAbsoluteLocation();
+ * location.add(1, 1); viewer.secondClick(new Click(keyboardFocus,
+ * location, modifiers)); //viewer.thirdClick(new Click(keyboardFocus,
+ * keyboardFocus.getLocation(), modifiers)); return; }
+ */
+
+ if (keyCode == KeyEvent.VK_F4 && (modifiers & InputEvent.CTRL_MASK) == InputEvent.CTRL_MASK) {
+ // TODO close window
+ return;
+ }
+
+ if (keyCode == KeyEvent.VK_DOWN) {
+ focusManager.focusFirstChildView();
+ // focusNextSubview(keyboardFocus);
+ return;
+ }
+
+ if (keyCode == KeyEvent.VK_UP) {
+ focusManager.focusParentView();
+ // focusPreviousSubview(keyboardFocus);
+ return;
+ }
+
+ if (keyCode == KeyEvent.VK_HOME) {
+ viewer.makeRootFocus();
+ return;
+ }
+
+ if (keyCode == KeyEvent.VK_RIGHT) {
+ focusManager.focusNextView();
+ // focusNextPeerView(keyboardFocus);
+ return;
+ }
+
+ if (keyCode == KeyEvent.VK_LEFT) {
+ focusManager.focusPreviousView();
+ // focusPreviousPeerView(keyboardFocus);
+ return;
+ }
+
+ int action = 0;
+
+ if (keyCode == KeyEvent.VK_F1) {
+ viewer.openHelp(keyboardFocus);
+ } else if (keyCode == KeyEvent.VK_TAB) {
+ action = tab(modifiers);
+ }
+
+ switch (action) {
+ case KeyboardAction.NEXT_VIEW:
+ focusManager.focusNextView();
+ // focusNextSubview(keyboardFocus);
+ break;
+ case KeyboardAction.PREVIOUS_VIEW:
+ focusManager.focusPreviousView();
+ // focusPreviousSubview(keyboardFocus);
+ break;
+ case KeyboardAction.NEXT_WINDOW:
+ focusManager.focusParentView();
+ // focusNextRootView(keyboardFocus);
+ break;
+ case KeyboardAction.PREVIOUS_WINDOW:
+ focusManager.focusFirstChildView();
+ break;
+ }
+ }
+
+ private boolean ignoreKey(final int keyCode) {
+ return keyCode == KeyEvent.VK_SHIFT || keyCode == KeyEvent.VK_CONTROL || keyCode == KeyEvent.VK_ALT;
+ }
+
+ private int tab(final int modifiers) {
+ int action;
+ if ((modifiers & InputEvent.CTRL_MASK) == InputEvent.CTRL_MASK) {
+ if ((modifiers & InputEvent.SHIFT_MASK) == InputEvent.SHIFT_MASK) {
+ action = KeyboardAction.PREVIOUS_WINDOW;
+ } else {
+ action = KeyboardAction.NEXT_WINDOW;
+ }
+ } else {
+ if ((modifiers & InputEvent.SHIFT_MASK) == InputEvent.SHIFT_MASK) {
+ action = KeyboardAction.PREVIOUS_VIEW;
+ } else {
+ action = KeyboardAction.NEXT_VIEW;
+ }
+ }
+ return action;
+ }
+
+ public void released(final int keyCode, final int modifiers) {
+ if (ignoreKey(keyCode)) {
+ return;
+ }
+
+ LOG.debug("key " + KeyEvent.getKeyText(keyCode) + " released\n");
+ final View keyboardFocus = getFocus();
+ if (keyboardFocus != null) {
+ keyboardFocus.keyReleased(new KeyboardActionImpl(keyCode, modifiers));
+ }
+ }
+
+ public void typed(final char keyChar) {
+ LOG.debug("typed '" + keyChar + "'");
+
+ if (viewer.isOverlayAvailable()) {
+ viewer.getOverlayView().keyTyped(new KeyboardActionImpl(keyChar, 0));
+ return;
+ }
+
+ final View keyboardFocus = getFocus();
+ if (keyboardFocus != null) {
+ if (!Character.isISOControl(keyChar)) {
+ keyboardFocus.keyTyped(new KeyboardActionImpl(keyChar, 0));
+ }
+ }
+ }
+
+ public FocusManager getFocusManager() {
+ return focusManager;
+ }
+
+ public void setFocusManager(final FocusManager focusManager) {
+ if (focusManager == null) {
+ throw new IsisException("No focus manager set up");
+ }
+ this.focusManager = focusManager;
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/LoginDialog.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/LoginDialog.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/LoginDialog.java
new file mode 100644
index 0000000..fb13b5e
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/LoginDialog.java
@@ -0,0 +1,241 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.isis.viewer.dnd.awt;
+
+import java.awt.BorderLayout;
+import java.awt.Button;
+import java.awt.Color;
+import java.awt.Cursor;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.Frame;
+import java.awt.GridLayout;
+import java.awt.Insets;
+import java.awt.Label;
+import java.awt.Panel;
+import java.awt.TextField;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.core.commons.authentication.AuthenticationSession;
+import org.apache.isis.core.commons.lang.StringUtils;
+import org.apache.isis.core.runtime.authentication.AuthenticationManager;
+import org.apache.isis.core.runtime.authentication.AuthenticationRequestPassword;
+
+public class LoginDialog extends Frame implements ActionListener, KeyListener {
+ private static final long serialVersionUID = 1L;
+ private static final Logger LOG = Logger.getLogger(LoginDialog.class);
+ private final static int BORDER = 12;
+ private TextField user;
+ private TextField password;
+ private Button cancel;
+ private Button login;
+
+ private static String CANCEL_LABEL = " Cancel ";
+ private static String LOGIN_LABEL = " Login ";
+ private boolean logIn = true;
+ private final AuthenticationManager authenticationManager;
+ private AuthenticationSession session;
+ private Label instructionLabel;
+
+ public LoginDialog(final AuthenticationManager authenticationManager) {
+ super("Apache Isis Login");
+ this.authenticationManager = authenticationManager;
+
+ setBackground(new Color(0xe0e0e0));
+
+ AWTUtilities.addWindowIcon(this, "login-logo.png");
+
+ addWindowListener(new WindowAdapter() {
+ @Override
+ public void windowClosing(final WindowEvent e) {
+ cancel(e.getComponent());
+ }
+ });
+
+ setLayout(new BorderLayout(0, 10));
+
+ createInstructionLabel();
+ createLoginFields();
+ createButtonsPanel();
+
+ setResizable(false);
+ pack();
+ final int height = getSize().height;
+ final int width = getFontMetrics(getFont()).charWidth('x') * 48;
+ setSize(width, height);
+ final Dimension screen = getToolkit().getScreenSize();
+
+ int x = (screen.width / 2) - (width / 2);
+
+ if ((screen.width / screen.height) >= 2) {
+ x = (screen.width / 4) - (width / 2);
+ }
+
+ final int y = (screen.height / 2) - (height / 2);
+ setLocation(x, y);
+ user.requestFocus();
+ }
+
+ private void createInstructionLabel() {
+ instructionLabel = new Label("Please enter your user name and password.");
+ add(instructionLabel, BorderLayout.NORTH);
+ }
+
+ private void createLoginFields() {
+ final Panel form = new Panel(new GridLayout(2, 2, 6, 8)) {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public Insets getInsets() {
+ return new Insets(12, 0, 6, 80);
+ }
+ };
+ add(form, BorderLayout.CENTER);
+
+ form.add(new Label("User name:", Label.RIGHT));
+ form.add(user = new TextField());
+ user.addKeyListener(this);
+
+ form.add(new Label("Password:", Label.RIGHT));
+ form.add(password = new TextField());
+ password.addKeyListener(this);
+ password.setEchoChar('*');
+ }
+
+ private void createButtonsPanel() {
+ final Panel buttons = new Panel(new FlowLayout(FlowLayout.RIGHT));
+ add(buttons, BorderLayout.SOUTH);
+
+ buttons.add(cancel = new Button(CANCEL_LABEL));
+ cancel.addActionListener(this);
+ cancel.addKeyListener(this);
+
+ buttons.add(login = new Button(LOGIN_LABEL));
+ login.addActionListener(this);
+ login.addKeyListener(this);
+ }
+
+ @Override
+ public Insets getInsets() {
+ final Insets in = super.getInsets();
+ in.top += BORDER;
+ in.bottom += BORDER / 2;
+ in.left += BORDER;
+ in.right += BORDER;
+ return in;
+ }
+
+ @Override
+ public void actionPerformed(final ActionEvent evt) {
+ action(evt.getSource());
+ }
+
+ @Override
+ public void keyPressed(final KeyEvent e) {
+ // ignore
+ }
+
+ @Override
+ public void keyReleased(final KeyEvent e) {
+ if (e.getKeyCode() == KeyEvent.VK_ENTER) {
+ action(e.getComponent());
+ }
+ if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
+ cancel(e.getComponent());
+ }
+ }
+
+ @Override
+ public void keyTyped(final KeyEvent e) {
+ // ignore
+ }
+
+ private synchronized void cancel(final Object widget) {
+ logIn = false;
+ notify();
+ }
+
+ private synchronized void action(final Object widget) {
+ if (widget == cancel) {
+ cancel(widget);
+ } else if (widget == login || widget == password) {
+ setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
+ instructionLabel.setText("Authorising...");
+ instructionLabel.setForeground(Color.BLACK);
+
+ final AuthenticationRequestPassword authenticationRequest = new AuthenticationRequestPassword(getUser(), getPassword());
+ session = authenticationManager.authenticate(authenticationRequest);
+ if (session == null) {
+ try {
+ Thread.sleep(750);
+ } catch (final InterruptedException ignore) {
+ }
+ instructionLabel.setText("Invalid user name or password; please try again.");
+ instructionLabel.setForeground(Color.RED);
+ } else {
+ logIn = true;
+ notify();
+ }
+ setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
+ } else if (widget == user) {
+ password.requestFocus();
+ }
+ }
+
+ @Override
+ public void dispose() {
+ LOG.debug("dispose...");
+ super.dispose();
+ LOG.debug("...disposed");
+
+ }
+
+ private String getUser() {
+ return StringUtils.removeTabs(user.getText()).trim();
+ }
+
+ public void setUserName(final String name) {
+ user.setText(name);
+ }
+
+ private String getPassword() {
+ return StringUtils.removeTabs(password.getText()).trim();
+ }
+
+ public AuthenticationSession getSession() {
+ return session;
+ }
+
+ public synchronized boolean login() {
+ try {
+ wait();
+ } catch (final InterruptedException e) {
+ }
+ return logIn;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/OverlayDebugFrame.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/OverlayDebugFrame.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/OverlayDebugFrame.java
new file mode 100644
index 0000000..c79b3a6
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/OverlayDebugFrame.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.isis.viewer.dnd.awt;
+
+import org.apache.isis.core.commons.debug.DebuggableWithTitle;
+import org.apache.isis.viewer.dnd.view.View;
+import org.apache.isis.viewer.dnd.view.base.AbstractView;
+import org.apache.isis.viewer.dnd.view.content.NullContent;
+import org.apache.isis.viewer.dnd.view.debug.DebugView;
+
+public class OverlayDebugFrame extends DebugFrame {
+ private static final long serialVersionUID = 1L;
+ private final XViewer viewer;
+
+ public OverlayDebugFrame(final XViewer viewer) {
+ super();
+ this.viewer = viewer;
+ }
+
+ @Override
+ protected DebuggableWithTitle[] getInfo() {
+ final View overlay = viewer.getOverlayView();
+ final DebugView debugView = new DebugView(overlay == null ? new EmptyView() : overlay);
+ return new DebuggableWithTitle[] { debugView };
+ }
+
+ class EmptyView extends AbstractView {
+ public EmptyView() {
+ super(new NullContent());
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/PrintOption.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/PrintOption.java b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/PrintOption.java
new file mode 100644
index 0000000..a1c19e6
--- /dev/null
+++ b/component/viewer/dnd/src/main/java/org/apache/isis/viewer/dnd/awt/PrintOption.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.isis.viewer.dnd.awt;
+
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.awt.Graphics;
+import java.awt.PrintJob;
+import java.awt.Toolkit;
+
+import org.apache.isis.core.metamodel.consent.Allow;
+import org.apache.isis.core.metamodel.consent.Consent;
+import org.apache.isis.viewer.dnd.drawing.Location;
+import org.apache.isis.viewer.dnd.view.View;
+import org.apache.isis.viewer.dnd.view.Workspace;
+import org.apache.isis.viewer.dnd.view.option.UserActionAbstract;
+
+public class PrintOption extends UserActionAbstract {
+ private final int HEIGHT = 60;
+ private final int LEFT = 60;
+
+ public PrintOption() {
+ super("Print...");
+ }
+
+ @Override
+ public Consent disabled(final View component) {
+ return Allow.DEFAULT;
+ }
+
+ @Override
+ public void execute(final Workspace workspace, final View view, final Location at) {
+ final Frame frame = new Frame();
+ final PrintJob job = Toolkit.getDefaultToolkit().getPrintJob(frame, "Print object", null);
+
+ if (job != null) {
+ final Graphics pg = job.getGraphics();
+ final Dimension pageSize = job.getPageDimension();
+
+ if (pg != null) {
+ pg.translate(LEFT, HEIGHT);
+ pg.drawRect(0, 0, pageSize.width - LEFT - 1, pageSize.height - HEIGHT - 1);
+ view.print(new PrintCanvas(pg, view));
+ pg.dispose();
+ }
+
+ job.end();
+ }
+ frame.dispose();
+ }
+
+ private class PrintCanvas extends AwtCanvas {
+ PrintCanvas(final Graphics g, final View view) {
+ super(g, null, 0, 0, view.getSize().getWidth(), view.getSize().getHeight());
+ }
+ }
+}