You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by le...@apache.org on 2015/09/27 20:04:44 UTC

svn commit: r1705561 [2/6] - in /pdfbox/trunk: ./ debugger/ debugger/src/ debugger/src/main/ debugger/src/main/java/ debugger/src/main/java/org/ debugger/src/main/java/org/apache/ debugger/src/main/java/org/apache/pdfbox/ debugger/src/main/java/org/apa...

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/OSXAdapter.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/OSXAdapter.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/OSXAdapter.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/OSXAdapter.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,225 @@
+/*
+ * 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.
+ * 
+ */
+
+/* 
+ * This file includes code under the following terms:
+ * 			
+ *  Version: 2.0
+ *  
+ *  Disclaimer: IMPORTANT:  This Apple software is supplied to you by 
+ *  Apple Inc. ("Apple") in consideration of your agreement to the
+ *  following terms, and your use, installation, modification or
+ *  redistribution of this Apple software constitutes acceptance of these
+ *  terms.  If you do not agree with these terms, please do not use,
+ *  install, modify or redistribute this Apple software.
+ *  
+ *  In consideration of your agreement to abide by the following terms, and
+ *  subject to these terms, Apple grants you a personal, non-exclusive
+ *  license, under Apple's copyrights in this original Apple software (the
+ *  "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ *  Software, with or without modifications, in source and/or binary forms;
+ *  provided that if you redistribute the Apple Software in its entirety and
+ *  without modifications, you must retain this notice and the following
+ *  text and disclaimers in all such redistributions of the Apple Software. 
+ *  Neither the name, trademarks, service marks or logos of Apple Inc. 
+ *  may be used to endorse or promote products derived from the Apple
+ *  Software without specific prior written permission from Apple.  Except
+ *  as expressly stated in this notice, no other rights or licenses, express
+ *  or implied, are granted by Apple herein, including but not limited to
+ *  any patent rights that may be infringed by your derivative works or by
+ *  other works in which the Apple Software may be incorporated.
+ *  
+ *  The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ *  MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ *  THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ *  FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ *  OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ *  
+ *  IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ *  OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *  INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ *  MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ *  AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ *  STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ *  
+ *  Copyright (C) 2003-2007 Apple, Inc., All Rights Reserved
+ */
+
+package org.apache.pdfbox.tools.gui;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+/**
+ * Hooks existing preferences/about/quit functionality from an
+ * existing Java app into handlers for the Mac OS X application menu.
+ * Uses a Proxy object to dynamically implement the 
+ * com.apple.eawt.ApplicationListener interface and register it with the
+ * com.apple.eawt.Application object.  This allows the complete project
+ * to be both built and run on any platform without any stubs or 
+ * placeholders. Useful for developers looking to implement Mac OS X 
+ * features while supporting multiple platforms with minimal impact.
+ */
+public class OSXAdapter implements InvocationHandler
+{
+
+    protected Object targetObject;
+    protected Method targetMethod;
+    protected String proxySignature;
+
+    static Object macOSXApplication;
+
+    // Pass this method an Object and Method equipped to perform application shutdown logic
+    // The method passed should return a boolean stating whether or not the quit should occur
+    public static void setQuitHandler(Object target, Method quitHandler) {
+        setHandler(new OSXAdapter("handleQuit", target, quitHandler));
+    }
+
+    // Pass this method an Object and Method equipped to display application info
+    // They will be called when the About menu item is selected from the application menu
+    public static void setAboutHandler(Object target, Method aboutHandler) {
+        boolean enableAboutMenu = (target != null && aboutHandler != null);
+        if (enableAboutMenu) {
+            setHandler(new OSXAdapter("handleAbout", target, aboutHandler));
+        }
+        // If we're setting a handler, enable the About menu item by calling
+        // com.apple.eawt.Application reflectively
+        try {
+            Method enableAboutMethod = macOSXApplication.getClass().getDeclaredMethod("setEnabledAboutMenu", new Class[] { boolean.class });
+            enableAboutMethod.invoke(macOSXApplication, new Object[] { Boolean.valueOf(enableAboutMenu) });
+        } catch (Exception ex) {
+            System.err.println("OSXAdapter could not access the About Menu");
+            throw new RuntimeException(ex);
+        }
+    }
+
+    // Pass this method an Object and a Method equipped to display application options
+    // They will be called when the Preferences menu item is selected from the application menu
+    public static void setPreferencesHandler(Object target, Method prefsHandler) {
+        boolean enablePrefsMenu = (target != null && prefsHandler != null);
+        if (enablePrefsMenu) {
+            setHandler(new OSXAdapter("handlePreferences", target, prefsHandler));
+        }
+        // If we're setting a handler, enable the Preferences menu item by calling
+        // com.apple.eawt.Application reflectively
+        try {
+            Method enablePrefsMethod = macOSXApplication.getClass().getDeclaredMethod("setEnabledPreferencesMenu", new Class[] { boolean.class });
+            enablePrefsMethod.invoke(macOSXApplication, new Object[] { Boolean.valueOf(enablePrefsMenu) });
+        } catch (Exception ex) {
+            System.err.println("OSXAdapter could not access the About Menu");
+            throw new RuntimeException(ex);
+        }
+    }
+
+    // Pass this method an Object and a Method equipped to handle document events from the Finder
+    // Documents are registered with the Finder via the CFBundleDocumentTypes dictionary in the 
+    // application bundle's Info.plist
+    public static void setFileHandler(Object target, Method fileHandler) {
+        setHandler(new OSXAdapter("handleOpenFile", target, fileHandler) {
+            // Override OSXAdapter.callTarget to send information on the
+            // file to be opened
+            public boolean callTarget(Object appleEvent) {
+                if (appleEvent != null) {
+                    try {
+                        Method getFilenameMethod = appleEvent.getClass().getDeclaredMethod("getFilename", (Class[])null);
+                        String filename = (String) getFilenameMethod.invoke(appleEvent, (Object[])null);
+                        this.targetMethod.invoke(this.targetObject, new Object[] { filename });
+                    } catch (Exception ex) {
+                        throw new RuntimeException(ex);
+                    }
+                }
+                return true;
+            }
+        });
+    }
+
+    // setHandler creates a Proxy object from the passed OSXAdapter and adds it as an ApplicationListener
+    public static void setHandler(OSXAdapter adapter) {
+        try {
+            Class<?> applicationClass = Class.forName("com.apple.eawt.Application");
+            if (macOSXApplication == null) {
+                macOSXApplication = applicationClass.getConstructor((Class[])null).newInstance((Object[])null);
+            }
+            Class<?> applicationListenerClass = Class.forName("com.apple.eawt.ApplicationListener");
+            Method addListenerMethod = applicationClass.getDeclaredMethod("addApplicationListener", new Class[] { applicationListenerClass });
+            // Create a proxy object around this handler that can be reflectively added as an Apple ApplicationListener
+            Object osxAdapterProxy = Proxy.newProxyInstance(OSXAdapter.class.getClassLoader(), new Class[]{applicationListenerClass}, adapter);
+            addListenerMethod.invoke(macOSXApplication, new Object[] { osxAdapterProxy });
+        } catch (ClassNotFoundException cnfe) {
+            System.err.println("This version of Mac OS X does not support the Apple EAWT.  ApplicationEvent handling has been disabled (" + cnfe + ")");
+        } catch (Exception ex) {  // Likely a NoSuchMethodException or an IllegalAccessException loading/invoking eawt.Application methods
+            System.err.println("Mac OS X Adapter could not talk to EAWT:");
+            throw new RuntimeException(ex);
+        }
+    }
+
+    // Each OSXAdapter has the name of the EAWT method it intends to listen for (handleAbout, for example),
+    // the Object that will ultimately perform the task, and the Method to be called on that Object
+    protected OSXAdapter(String proxySignature, Object target, Method handler) {
+        this.proxySignature = proxySignature;
+        this.targetObject = target;
+        this.targetMethod = handler;
+    }
+
+    // Override this method to perform any operations on the event 
+    // that comes with the various callbacks
+    // See setFileHandler above for an example
+    public boolean callTarget(Object appleEvent) throws InvocationTargetException, IllegalAccessException {
+        Object result = targetMethod.invoke(targetObject, (Object[])null);
+        if (result == null) {
+            return true;
+        }
+        return Boolean.valueOf(result.toString()).booleanValue();
+    }
+
+    // InvocationHandler implementation
+    // This is the entry point for our proxy object; it is called every time an ApplicationListener method is invoked
+    public Object invoke (Object proxy, Method method, Object[] args) throws Throwable {
+        if (isCorrectMethod(method, args)) {
+            boolean handled = callTarget(args[0]);
+            setApplicationEventHandled(args[0], handled);
+        }
+        // All of the ApplicationListener methods are void; return null regardless of what happens
+        return null;
+    }
+
+    // Compare the method that was called to the intended method when the OSXAdapter instance was created
+    // (e.g. handleAbout, handleQuit, handleOpenFile, etc.)
+    protected boolean isCorrectMethod(Method method, Object[] args) {
+        return (targetMethod != null && proxySignature.equals(method.getName()) && args.length == 1);
+    }
+
+    // It is important to mark the ApplicationEvent as handled and cancel the default behavior
+    // This method checks for a boolean result from the proxy method and sets the event accordingly
+    protected void setApplicationEventHandled(Object event, boolean handled) {
+        if (event != null) {
+            try {
+                Method setHandledMethod = event.getClass().getDeclaredMethod("setHandled", new Class[] { boolean.class });
+                // If the target method returns a boolean, use that as a hint
+                setHandledMethod.invoke(event, new Object[] { Boolean.valueOf(handled) });
+            } catch (Exception ex) {
+                System.err.println("OSXAdapter was unable to handle an ApplicationEvent: " + event);
+                throw new RuntimeException(ex);
+            }
+        }
+    }
+}

Propchange: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/OSXAdapter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/PDFTreeCellRenderer.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/PDFTreeCellRenderer.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/PDFTreeCellRenderer.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/PDFTreeCellRenderer.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,345 @@
+/*
+ * 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.pdfbox.tools.gui;
+
+import java.awt.Component;
+import java.awt.Graphics;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import javax.swing.ImageIcon;
+import javax.swing.JTree;
+import javax.swing.tree.DefaultTreeCellRenderer;
+import org.apache.pdfbox.cos.COSArray;
+import org.apache.pdfbox.cos.COSBase;
+import org.apache.pdfbox.cos.COSBoolean;
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSFloat;
+import org.apache.pdfbox.cos.COSInteger;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.cos.COSNull;
+import org.apache.pdfbox.cos.COSObject;
+import org.apache.pdfbox.cos.COSStream;
+import org.apache.pdfbox.cos.COSString;
+
+/**
+ * A class to render tree cells for the pdfviewer.
+ *
+ * @author Ben Litchfield
+ */
+public class PDFTreeCellRenderer extends DefaultTreeCellRenderer
+{
+    private static final ImageIcon ICON_ARRAY = new ImageIcon(getImageUrl("array"));
+    private static final ImageIcon ICON_BOOLEAN = new ImageIcon(getImageUrl("boolean"));
+    private static final ImageIcon ICON_DICT = new ImageIcon(getImageUrl("dict"));
+    private static final ImageIcon ICON_HEX = new ImageIcon(getImageUrl("hex"));
+    private static final ImageIcon ICON_INDIRECT = new ImageIcon(getImageUrl("indirect"));
+    private static final ImageIcon ICON_INTEGER = new ImageIcon(getImageUrl("integer"));
+    private static final ImageIcon ICON_NAME = new ImageIcon(getImageUrl("name"));
+    private static final ImageIcon ICON_NULL = new ImageIcon(getImageUrl("null"));
+    private static final ImageIcon ICON_REAL = new ImageIcon(getImageUrl("real"));
+    private static final ImageIcon ICON_STREAM_DICT = new ImageIcon(getImageUrl("stream-dict"));
+    private static final ImageIcon ICON_STRING = new ImageIcon(getImageUrl("string"));
+    private static final ImageIcon ICON_PDF = new ImageIcon(getImageUrl("pdf"));
+    private static final ImageIcon ICON_PAGE = new ImageIcon(getImageUrl("page"));
+
+    private static URL getImageUrl(String name)
+    {
+        String fullName = "/org/apache/pdfbox/tools/pdfdebugger/" + name + ".png";
+        return PDFTreeCellRenderer.class.getResource(fullName);
+    }
+    
+    @Override
+    public Component getTreeCellRendererComponent(
+            JTree tree,
+            Object nodeValue,
+            boolean isSelected,
+            boolean expanded,
+            boolean leaf,
+            int row,
+            boolean componentHasFocus)
+    {
+        Component component = super.getTreeCellRendererComponent(tree,
+                toTreeObject(nodeValue),
+                isSelected, expanded, leaf, row, componentHasFocus);
+        
+        setIcon(lookupIconWithOverlay(nodeValue));
+
+        return component;
+    }
+
+    private Object toTreeObject(Object nodeValue)
+    {
+        Object result = nodeValue;
+        if (nodeValue instanceof MapEntry || nodeValue instanceof ArrayEntry)
+        {
+            String key;
+            Object object;
+            Object value;
+            COSBase item;
+            if (nodeValue instanceof MapEntry)
+            {
+                MapEntry entry = (MapEntry) nodeValue;
+                key = entry.getKey().getName();
+                object = toTreeObject(entry.getValue());
+                value = entry.getValue();
+                item = entry.getItem();
+            }
+            else
+            {
+                ArrayEntry entry = (ArrayEntry) nodeValue;
+                key = "" + entry.getIndex();
+                object = toTreeObject(entry.getValue());
+                value = entry.getValue();
+                item = entry.getItem();
+            }
+            
+            String stringResult = key;
+            if (object instanceof String && ((String)object).length() > 0)
+            {
+                stringResult += ":  " + object;
+                if (item instanceof COSObject)
+                {
+                    COSObject indirect = (COSObject)item;
+                    stringResult += " [" + indirect.getObjectNumber() + " " +
+                                           indirect.getGenerationNumber() + " R]";
+                }
+                stringResult += toTreePostfix(value);
+                
+            }
+            result = stringResult;
+        }
+        else if (nodeValue instanceof COSBoolean)
+        {
+            result = "" + ((COSBoolean) nodeValue).getValue();
+        }
+        else if (nodeValue instanceof COSFloat)
+        {
+            result = "" + ((COSFloat) nodeValue).floatValue();
+        }
+        else if (nodeValue instanceof COSInteger)
+        {
+            result = "" + ((COSInteger) nodeValue).intValue();
+        }
+        else if (nodeValue instanceof COSString)
+        {
+            String text = ((COSString) nodeValue).getString();
+            // display unprintable strings as hex
+            for (char c : text.toCharArray())
+            {
+                if (Character.isISOControl(c))
+                {
+                    text = "<" + ((COSString) nodeValue).toHexString() + ">";
+                    break;
+                }
+            }
+            result = text;
+        }
+        else if (nodeValue instanceof COSName)
+        {
+            result = ((COSName) nodeValue).getName();
+        }
+        else if (nodeValue instanceof COSNull || nodeValue == null)
+        {
+            result = "";
+        }
+        else if (nodeValue instanceof COSDictionary)
+        {
+            COSDictionary dict = (COSDictionary) nodeValue;
+            if (COSName.XREF.equals(dict.getCOSName(COSName.TYPE)))
+            {
+                result = "";
+            }
+            else
+            {
+                result = "(" + dict.size() + ")";
+            }
+        }
+        else if (nodeValue instanceof COSArray)
+        {
+            COSArray array = (COSArray) nodeValue;
+            result = "(" + array.size() + ")";
+        }
+        else if (nodeValue instanceof DocumentEntry)
+        {
+            result = nodeValue.toString();
+        }
+        return result;
+    }
+
+    private String toTreePostfix(Object nodeValue)
+    {
+        if (nodeValue instanceof COSDictionary)
+        {
+            StringBuilder sb = new StringBuilder();
+            
+            COSDictionary dict = (COSDictionary)nodeValue;
+            if (dict.containsKey(COSName.TYPE))
+            {
+                COSName type = dict.getCOSName(COSName.TYPE);
+                sb.append("   /T:").append(type.getName());
+            }
+            
+            if (dict.containsKey(COSName.SUBTYPE))
+            {
+                COSName subtype = dict.getCOSName(COSName.SUBTYPE);
+                sb.append("  /S:").append(subtype.getName());
+            }
+            return sb.toString();
+        }
+        else
+        {
+            return "";
+        }
+    }
+
+    private ImageIcon lookupIconWithOverlay(Object nodeValue)
+    {
+        ImageIcon icon = lookupIcon(nodeValue);
+        boolean isIndirect = false;
+        boolean isStream = false;
+        
+        if (nodeValue instanceof MapEntry)
+        {
+            MapEntry entry = (MapEntry) nodeValue;
+            if (entry.getItem() instanceof COSObject)
+            {
+                isIndirect = true;
+                isStream = entry.getValue() instanceof COSStream;
+            }
+        }
+        else if (nodeValue instanceof ArrayEntry)
+        {
+            ArrayEntry entry = (ArrayEntry) nodeValue;
+            if (entry.getItem() instanceof COSObject)
+            {
+                isIndirect = true;
+                isStream = entry.getValue() instanceof COSStream;
+            }
+        }
+        
+        if (isIndirect && !isStream)
+        {
+            OverlayIcon overlay = new OverlayIcon(icon);
+            overlay.add(ICON_INDIRECT);
+            return overlay;
+        }
+        return icon;
+    }
+    
+    private ImageIcon lookupIcon(Object nodeValue)
+    {
+        if (nodeValue instanceof MapEntry)
+        {
+            MapEntry entry = (MapEntry) nodeValue;
+            return lookupIcon(entry.getValue());
+        }
+        else if (nodeValue instanceof ArrayEntry)
+        {
+            ArrayEntry entry = (ArrayEntry) nodeValue;
+            return lookupIcon(entry.getValue());
+        }
+        else if (nodeValue instanceof COSBoolean)
+        {
+            return ICON_BOOLEAN;
+        }
+        else if (nodeValue instanceof COSFloat)
+        {
+            return ICON_REAL;
+        }
+        else if (nodeValue instanceof COSInteger)
+        {
+            return ICON_INTEGER;
+        }
+        else if (nodeValue instanceof COSString)
+        {
+            String text = ((COSString) nodeValue).getString();
+            // display unprintable strings as hex
+            for (char c : text.toCharArray())
+            {
+                if (Character.isISOControl(c))
+                {
+                    return ICON_HEX;
+                }
+            }
+            return ICON_STRING;
+        }
+        else if (nodeValue instanceof COSName)
+        {
+            return ICON_NAME;
+        }
+        else if (nodeValue instanceof COSNull || nodeValue == null)
+        {
+            return ICON_NULL;
+        }
+        else if (nodeValue instanceof COSStream)
+        {
+            return ICON_STREAM_DICT;
+        }
+        else if (nodeValue instanceof COSDictionary)
+        {
+            return ICON_DICT;
+        }
+        else if (nodeValue instanceof COSArray)
+        {
+            return ICON_ARRAY;
+        }
+        else if (nodeValue instanceof DocumentEntry)
+        {
+            return ICON_PDF;
+        }
+        else if (nodeValue instanceof PageEntry)
+        {
+            return ICON_PAGE;
+        }
+        else
+        {
+            return null;
+        }
+    }
+
+    /**
+     * An ImageIcon which allows other ImageIcon overlays.
+     */
+    private class OverlayIcon extends ImageIcon
+    {
+        private final ImageIcon base;
+        private final List<ImageIcon> overlays;
+
+        OverlayIcon(ImageIcon base)
+        {
+            super(base.getImage());
+            this.base = base;
+            this.overlays = new ArrayList<ImageIcon>();
+        }
+
+        void add(ImageIcon overlay)
+        {
+            overlays.add(overlay);
+        }
+
+        @Override
+        public synchronized void paintIcon(Component c, Graphics g, int x, int y)
+        {
+            base.paintIcon(c, g, x, y);
+            for (ImageIcon icon: overlays)
+            {
+                icon.paintIcon(c, g, x, y);
+            }
+        }
+    }
+}

Propchange: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/PDFTreeCellRenderer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/PDFTreeModel.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/PDFTreeModel.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/PDFTreeModel.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/PDFTreeModel.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,348 @@
+/*
+ * 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.pdfbox.tools.gui;
+
+/**
+ * A tree model that uses a cos document.
+ *
+ *
+ * @author wurtz
+ * @author Ben Litchfield
+ */
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import javax.swing.event.TreeModelListener;
+import javax.swing.tree.TreeModel;
+import javax.swing.tree.TreePath;
+import org.apache.pdfbox.cos.COSArray;
+import org.apache.pdfbox.cos.COSBase;
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSDocument;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.cos.COSObject;
+import org.apache.pdfbox.pdmodel.PDDocument;
+
+/**
+ * A class to model a PDF document as a tree structure.
+ *
+ * @author Ben Litchfield
+ */
+public class PDFTreeModel implements TreeModel
+{
+    private Object root;
+
+    /**
+     * constructor.
+     */
+    public PDFTreeModel()
+    {
+        //default constructor
+    }
+
+    /**
+     * Constructor to take a document.
+     *
+     * @param doc The document to display in the tree.
+     */
+    public PDFTreeModel(PDDocument doc)
+    {
+        root = doc.getDocument().getTrailer();
+    }
+
+    /**
+     * Constructor to take a document.
+     *
+     * @param docEntry The document to display in the tree.
+     */
+    public PDFTreeModel(DocumentEntry docEntry)
+    {
+        root = docEntry;
+    }
+
+    /**
+     * Adds a listener for the <code>TreeModelEvent</code>
+     * posted after the tree changes.
+     *
+     * @param   l       the listener to add
+     * @see     #removeTreeModelListener
+     *
+     */
+    @Override
+    public void addTreeModelListener(TreeModelListener l)
+    {
+        //required for interface
+    }
+
+    /**
+     * Returns the child of <code>parent</code> at index <code>index</code> in the parent's child
+     * array. <code>parent</code> must be a node previously obtained from this data source. This
+     * should not return <code>null</code> if <code>index</code> is a valid index for
+     * <code>parent</code> (that is <code>index &gt;= 0 &&
+     * index &lt; getChildCount(parent</code>)).
+     *
+     * @param parent a node in the tree, obtained from this data source
+     * @param index The index into the parent object to location the child object.
+     * @return the child of <code>parent</code> at index <code>index</code>
+     * @throws IllegalArgumentException if an unknown unknown COS type is passed as parent
+     * parameter.
+     */
+    @Override
+    public Object getChild(Object parent, int index)
+    {
+        Object retval = null;
+        if( parent instanceof COSArray )
+        {
+            ArrayEntry entry = new ArrayEntry();
+            entry.setIndex( index );
+            entry.setValue( ((COSArray)parent).getObject(index) );
+            entry.setItem(((COSArray) parent).get(index));
+            retval = entry;
+        }
+        else if( parent instanceof COSDictionary )
+        {
+            COSDictionary dict = (COSDictionary)parent;
+            List<COSName> keys = new ArrayList<COSName>(dict.keySet());
+            Collections.sort( keys );
+            COSName key = keys.get( index );
+            COSBase value = dict.getDictionaryObject(key);
+            MapEntry entry = new MapEntry();
+            entry.setKey( key );
+            entry.setValue( value );
+            entry.setItem(dict.getItem(key));
+            retval = entry;
+        }
+        else if( parent instanceof MapEntry )
+        {
+            retval = getChild( ((MapEntry)parent).getValue(), index );
+        }
+        else if( parent instanceof ArrayEntry )
+        {
+            retval = getChild( ((ArrayEntry)parent).getValue(), index );
+        }
+        else if( parent instanceof COSDocument )
+        {
+            retval = ((COSDocument)parent).getObjects().get( index );
+        }
+        else if( parent instanceof DocumentEntry)
+        {
+            retval = ((DocumentEntry)parent).getPage(index);
+        }
+        else if( parent instanceof PageEntry)
+        {
+            retval = getChild(((PageEntry)parent).getDict(), index);
+        }
+        else if( parent instanceof COSObject )
+        {
+            retval = ((COSObject)parent).getObject();
+        }
+        else
+        {
+            throw new IllegalArgumentException("Unknown COS type " + parent.getClass().getName());
+        }
+        return retval;
+    }
+
+    /** Returns the number of children of <code>parent</code>.
+     * Returns 0 if the node
+     * is a leaf or if it has no children.  <code>parent</code> must be a node
+     * previously obtained from this data source.
+     *
+     * @param   parent  a node in the tree, obtained from this data source
+     * @return  the number of children of the node <code>parent</code>
+     *
+     */
+    @Override
+    public int getChildCount(Object parent)
+    {
+        int retval = 0;
+        if( parent instanceof COSArray )
+        {
+            retval = ((COSArray)parent).size();
+        }
+        else if( parent instanceof COSDictionary )
+        {
+            retval = ((COSDictionary)parent).size();
+        }
+        else if( parent instanceof MapEntry )
+        {
+            retval = getChildCount(((MapEntry) parent).getValue());
+        }
+        else if( parent instanceof ArrayEntry )
+        {
+            retval = getChildCount(((ArrayEntry) parent).getValue());
+        }
+        else if( parent instanceof COSDocument )
+        {
+            retval = ((COSDocument)parent).getObjects().size();
+        }
+        else if( parent instanceof DocumentEntry )
+        {
+            retval = ((DocumentEntry)parent).getPageCount();
+        }
+        else if( parent instanceof PageEntry)
+        {
+            retval = getChildCount(((PageEntry) parent).getDict());
+        }
+        else if( parent instanceof COSObject )
+        {
+            retval = 1;
+        }
+        return retval;
+    }
+
+    /**
+     * Returns the index of child in parent. If <code>parent</code> is <code>null</code> or
+     * <code>child</code> is <code>null</code>, returns -1.
+     *
+     * @param parent a node in the tree, obtained from this data source
+     * @param child the node we are interested in
+     * @return the index of the child in the parent, or -1 if either <code>child</code> or
+     * <code>parent</code> are <code>null</code>
+     * @throws IllegalArgumentException if an unknown unknown COS type is passed as parent parameter.
+     */
+    @Override
+    public int getIndexOfChild(Object parent, Object child)
+    {
+        int retval = -1;
+        if( parent != null && child != null )
+        {
+            if( parent instanceof COSArray )
+            {
+                COSArray array = (COSArray)parent;
+                if( child instanceof ArrayEntry )
+                {
+                    ArrayEntry arrayEntry = (ArrayEntry)child;
+                    retval = arrayEntry.getIndex();
+                }
+                else
+                {
+                    retval = array.indexOf( (COSBase)child );
+                }
+            }
+            else if( parent instanceof COSDictionary )
+            {
+                MapEntry entry = (MapEntry)child;
+                COSDictionary dict = (COSDictionary)parent;
+                List<COSName> keys = new ArrayList<COSName>(dict.keySet());
+                Collections.sort( keys );
+                for( int i=0; retval == -1 && i<keys.size(); i++ )
+                {
+                    if( keys.get( i ).equals( entry.getKey() ) )
+                    {
+                        retval = i;
+                    }
+                }
+            }
+            else if( parent instanceof MapEntry )
+            {
+                retval = getIndexOfChild( ((MapEntry)parent).getValue(), child );
+            }
+            else if( parent instanceof ArrayEntry )
+            {
+                retval = getIndexOfChild( ((ArrayEntry)parent).getValue(), child );
+            }
+            else if( parent instanceof COSDocument )
+            {
+                retval = ((COSDocument)parent).getObjects().indexOf( child );
+            }
+            else if( parent instanceof DocumentEntry )
+            {
+                retval = ((DocumentEntry)parent).indexOf( (PageEntry)child );
+            }
+            else if( parent instanceof PageEntry)
+            {
+                retval = getIndexOfChild(((PageEntry)parent).getDict(), child);
+            }
+            else if( parent instanceof COSObject )
+            {
+                retval = 0;
+            }
+            else
+            {
+                throw new IllegalArgumentException("Unknown COS type " + parent.getClass().getName());
+            }
+        }
+        return retval;
+    }
+
+    /** Returns the root of the tree.  Returns <code>null</code>
+     * only if the tree has no nodes.
+     *
+     * @return  the root of the tree
+     *
+     */
+    @Override
+    public Object getRoot()
+    {
+        return root;
+    }
+
+    /** Returns <code>true</code> if <code>node</code> is a leaf.
+     * It is possible for this method to return <code>false</code>
+     * even if <code>node</code> has no children.
+     * A directory in a filesystem, for example,
+     * may contain no files; the node representing
+     * the directory is not a leaf, but it also has no children.
+     *
+     * @param   node  a node in the tree, obtained from this data source
+     * @return  true if <code>node</code> is a leaf
+     *
+     */
+    @Override
+    public boolean isLeaf(Object node)
+    {
+        boolean isLeaf = !(node instanceof COSDictionary ||
+                 node instanceof COSArray ||
+                 node instanceof COSDocument ||
+                 node instanceof DocumentEntry ||
+                 node instanceof PageEntry ||
+                 node instanceof COSObject ||
+                 (node instanceof MapEntry && !isLeaf(((MapEntry)node).getValue()) ) ||
+                 (node instanceof ArrayEntry && !isLeaf(((ArrayEntry)node).getValue()) ));
+        return isLeaf;
+    }
+
+    /** Removes a listener previously added with
+     * <code>addTreeModelListener</code>.
+     *
+     * @see     #addTreeModelListener
+     * @param   l       the listener to remove
+     *
+     */
+
+    @Override
+    public void removeTreeModelListener(TreeModelListener l)
+    {
+        //required for interface
+    }
+
+    /** Messaged when the user has altered the value for the item identified
+     * by <code>path</code> to <code>newValue</code>.
+     * If <code>newValue</code> signifies a truly new value
+     * the model should post a <code>treeNodesChanged</code> event.
+     *
+     * @param path path to the node that the user has altered
+     * @param newValue the new value from the TreeCellEditor
+     *
+     */
+    @Override
+    public void valueForPathChanged(TreePath path, Object newValue)
+    {
+        //required for interface
+    }
+}

Propchange: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/PDFTreeModel.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/PageEntry.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/PageEntry.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/PageEntry.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/PageEntry.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,72 @@
+/*
+ * 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.pdfbox.tools.gui;
+
+import org.apache.pdfbox.cos.COSArray;
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSName;
+
+/**
+ * Represents an abstract view of a page in the tree view.
+ *
+ * @author John Hewson
+ */
+public class PageEntry
+{
+    private final COSDictionary dict;
+    private final int pageNum;
+    
+    public PageEntry(COSDictionary page, int pageNum)
+    {
+        dict = page;
+        this.pageNum = pageNum;
+    }
+    
+    public COSDictionary getDict()
+    {
+        return dict;
+    }
+
+    public int getPageNum()
+    {
+        return pageNum;
+    }
+    
+    @Override
+    public String toString()
+    {
+        return "Page: " + pageNum;
+    }
+    
+    public String getPath()
+    {
+        StringBuilder sb = new StringBuilder();
+        sb.append("Root/Pages");
+        
+        COSDictionary node = dict;
+        while (node.containsKey(COSName.PARENT))
+        {
+            COSDictionary parent = (COSDictionary)node.getDictionaryObject(COSName.PARENT);
+            COSArray kids = (COSArray)parent.getDictionaryObject(COSName.KIDS);
+            int idx = kids.indexOfObject(node);
+            sb.append("/Kids/[").append(idx).append("]");
+            node = parent;
+        }
+        return sb.toString();
+    }
+}

Propchange: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/PageEntry.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/ReaderBottomPanel.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/ReaderBottomPanel.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/ReaderBottomPanel.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/ReaderBottomPanel.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,59 @@
+/*
+ * 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.pdfbox.tools.gui;
+
+import java.awt.Dimension;
+
+import javax.swing.JPanel;
+
+import javax.swing.JLabel;
+import java.awt.FlowLayout;
+/**
+ * A panel to display at the bottom of the window for status and other stuff.
+ *
+ * @author Ben Litchfield
+ */
+public class ReaderBottomPanel extends JPanel
+{
+
+    private JLabel statusLabel = null;
+
+    /**
+     * This is the default constructor.
+     */
+    public ReaderBottomPanel()
+    {
+        FlowLayout flowLayout = new FlowLayout();
+        this.setLayout(flowLayout);
+        this.setComponentOrientation(java.awt.ComponentOrientation.LEFT_TO_RIGHT);
+        this.setPreferredSize(new Dimension(1000, 20));
+        flowLayout.setAlignment(FlowLayout.LEFT);
+        statusLabel = new JLabel();
+        statusLabel.setText("Ready");
+        this.add(statusLabel, null);
+    }
+
+    /**
+     * Return the status label.
+     *
+     * @return JLabel The status label.
+     */
+    public JLabel getStatusLabel()
+    {
+        return statusLabel;
+    }
+}

Propchange: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/ReaderBottomPanel.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/CSArrayBased.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/CSArrayBased.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/CSArrayBased.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/CSArrayBased.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2015 The Apache Software Foundation.
+ *
+ * Licensed 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.pdfbox.tools.pdfdebugger.colorpane;
+
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.io.IOException;
+import javax.swing.BoxLayout;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import org.apache.pdfbox.cos.COSArray;
+import org.apache.pdfbox.pdmodel.graphics.color.PDColorSpace;
+import org.apache.pdfbox.pdmodel.graphics.color.PDPattern;
+
+/**
+ *
+ * @author Tilman Hausherr
+ *
+ * Simple pane to show a title and detail on the color spaces that have no visual "magic".
+ */
+public class CSArrayBased
+{
+    private JPanel panel;
+    private PDColorSpace colorSpace = null;
+    private int numberOfComponents = 0;
+    private String errmsg = "";
+
+    public CSArrayBased(COSArray array)
+    {
+        try
+        {
+            colorSpace = PDColorSpace.create(array);
+            if (!(colorSpace instanceof PDPattern))
+            {
+                numberOfComponents = colorSpace.getNumberOfComponents();
+            }
+        }
+        catch (IOException ex)
+        {
+            errmsg = ex.getMessage();
+        }
+        initUI();
+    }
+
+    private void initUI()
+    {
+        panel = new JPanel();
+        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
+        panel.setPreferredSize(new Dimension(300, 500));
+
+        if (colorSpace == null)
+        {
+            JLabel error = new JLabel(errmsg);
+            error.setAlignmentX(Component.CENTER_ALIGNMENT);
+            error.setFont(new Font(Font.MONOSPACED, Font.BOLD, 15));
+            panel.add(error);
+            return;
+        }
+        
+        JLabel colorSpaceLabel = new JLabel(colorSpace.getName() + " colorspace");
+        colorSpaceLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
+        colorSpaceLabel.setFont(new Font(Font.MONOSPACED, Font.BOLD, 30));
+        panel.add(colorSpaceLabel);
+
+        if (numberOfComponents > 0)
+        {
+            JLabel colorCountLabel = new JLabel("Component Count: " + numberOfComponents);
+            colorCountLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
+            colorCountLabel.setFont(new Font(Font.MONOSPACED, Font.BOLD, 20));
+            panel.add(colorCountLabel);
+        }
+    }
+
+    /**
+     * return the main panel that hold all the UI elements.
+     *
+     * @return JPanel instance
+     */
+    public Component getPanel()
+    {
+        return panel;
+    }
+
+}

Propchange: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/CSArrayBased.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/CSDeviceN.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/CSDeviceN.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/CSDeviceN.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/CSDeviceN.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,128 @@
+/*
+ * 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.pdfbox.tools.pdfdebugger.colorpane;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.util.Arrays;
+import javax.swing.BoxLayout;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import java.io.IOException;
+
+import org.apache.pdfbox.cos.COSArray;
+import org.apache.pdfbox.pdmodel.graphics.color.PDDeviceN;
+
+
+/**
+ *@author Khyrul Bashar.
+ */
+
+/**
+ * A class that provides the necessary UI and functionalities to show the DeviceN color space.
+ */
+public class CSDeviceN
+{
+    private PDDeviceN deviceN;
+    private JPanel panel;
+
+    /**
+     * Constructor
+     *
+     * @param array COSArray instance that holds DeviceN color space
+     */
+    public CSDeviceN(COSArray array)
+    {
+        try
+        {
+            deviceN = new PDDeviceN(array);
+            DeviceNColorant[] colorants = getColorantData();
+            initUI(colorants);
+        }
+        catch (IOException e)
+        {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Parses the colorant data from the array.
+     *
+     * @return the parsed colorants.
+     * @throws java.io.IOException if the color conversion fails.
+     */
+    private DeviceNColorant[] getColorantData() throws IOException
+    {
+        int componentCount = deviceN.getNumberOfComponents();
+        DeviceNColorant[] colorants = new DeviceNColorant[componentCount];
+        for (int i = 0; i < componentCount; i++)
+        {
+            DeviceNColorant colorant = new DeviceNColorant();
+
+            colorant.setName(deviceN.getColorantNames().get(i));
+            float[] maximum = new float[componentCount];
+            Arrays.fill(maximum, 0);
+            float[] minimum = new float[componentCount];
+            Arrays.fill(minimum, 0);
+            maximum[i] = 1;
+            colorant.setMaximum(getColorObj(deviceN.toRGB(maximum)));
+            colorant.setMinimum(getColorObj(deviceN.toRGB(minimum)));
+            colorants[i] = colorant;
+        }
+        return colorants;
+    }
+
+    private void initUI(DeviceNColorant[] colorants)
+    {
+        panel = new JPanel();
+        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
+        panel.setPreferredSize(new Dimension(300, 500));
+
+        JLabel colorSpaceLabel = new JLabel("DeviceN colorspace");
+        colorSpaceLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
+        colorSpaceLabel.setFont(new Font(Font.MONOSPACED, Font.BOLD, 30));
+
+        DeviceNTableModel tableModel = new DeviceNTableModel(colorants);
+        JTable table = new JTable(tableModel);
+        table.setDefaultRenderer(Color.class, new ColorBarCellRenderer());
+        table.setRowHeight(60);
+        JScrollPane scrollPane = new JScrollPane();
+        scrollPane.setViewportView(table);
+
+        panel.add(colorSpaceLabel);
+        panel.add(scrollPane);
+    }
+
+    /**
+     * return the main panel that hold all the UI elements.
+     *
+     * @return JPanel instance
+     */
+    public Component getPanel()
+    {
+        return panel;
+    }
+
+    private Color getColorObj(float[] rgbValues)
+    {
+        return new Color(rgbValues[0], rgbValues[1], rgbValues[2]);
+    }
+}

Propchange: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/CSDeviceN.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/CSIndexed.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/CSIndexed.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/CSIndexed.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/CSIndexed.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,155 @@
+/*
+ * 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.pdfbox.tools.pdfdebugger.colorpane;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.io.IOException;
+import javax.swing.Box;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+
+import org.apache.pdfbox.cos.COSArray;
+import org.apache.pdfbox.cos.COSNumber;
+import org.apache.pdfbox.pdmodel.graphics.color.PDIndexed;
+
+/**
+ * @author Khyrul Bashar.
+ */
+
+/**
+ * A class that provides the necessary UI and functionalities to show the Indexed colorspace.
+ */
+public class CSIndexed
+{
+    private PDIndexed indexed;
+    private JPanel panel;
+    private int colorCount;
+
+    /**
+     * Constructor.
+     * @param array COSArray instance for Indexed Colorspace.
+     */
+    public CSIndexed(COSArray array)
+    {
+        try
+        {
+            indexed = new PDIndexed(array);
+            colorCount = getHival(array);
+            initUI(getColorantData());
+        }
+        catch (IOException e)
+        {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Parses the colorant data from the array and return.
+     *
+     * @return
+     */
+    private IndexedColorant[] getColorantData()
+    {
+        IndexedColorant[] colorants = new IndexedColorant[colorCount];
+        for (int i = 0; i < colorCount; i++)
+        {
+            IndexedColorant colorant = new IndexedColorant();
+            colorant.setIndex(i);
+
+            float[] rgbValues = indexed.toRGB(new float[]{i});
+            colorant.setRgbValues(rgbValues);
+            colorants[i] = colorant;
+        }
+        return colorants;
+    }
+
+    private void initUI(IndexedColorant[] colorants)
+    {
+        panel = new JPanel();
+        panel.setLayout(new GridBagLayout());
+        panel.setPreferredSize(new Dimension(300, 500));
+
+        JLabel colorSpaceLabel = new JLabel("Indexed colorspace");
+        colorSpaceLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
+        colorSpaceLabel.setFont(new Font(Font.MONOSPACED, Font.BOLD, 30));
+        JPanel colorspaceLabelPanel = new JPanel();
+        colorspaceLabelPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
+        colorspaceLabelPanel.add(colorSpaceLabel);
+
+        JLabel colorCountLabel = new JLabel(" Total Color Count: " + colorCount);
+        colorCountLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
+        colorCountLabel.setFont(new Font(Font.MONOSPACED, Font.BOLD, 20));
+
+        IndexedTableModel tableModel = new IndexedTableModel(colorants);
+        JTable table = new JTable(tableModel);
+        table.setDefaultRenderer(Color.class, new ColorBarCellRenderer());
+        table.setRowHeight(40);
+        table.getColumnModel().getColumn(0).setMinWidth(30);
+        table.getColumnModel().getColumn(0).setMaxWidth(50);
+        table.getColumnModel().getColumn(1).setMinWidth(100);
+        table.getColumnModel().getColumn(1).setMaxWidth(100);
+
+        JScrollPane scrollPane = new JScrollPane();
+        scrollPane.setViewportView(table);
+        scrollPane.setAlignmentX(Component.LEFT_ALIGNMENT);
+
+        Box box = Box.createVerticalBox();
+        box.add(colorCountLabel);
+        box.add(scrollPane);
+        box.setAlignmentX(Component.LEFT_ALIGNMENT);
+
+        GridBagConstraints gbc = new GridBagConstraints();
+        gbc.gridx = 0;
+        gbc.gridy = 0;
+        gbc.weighty = 0.05;
+        gbc.fill = GridBagConstraints.HORIZONTAL;
+        gbc.anchor = GridBagConstraints.PAGE_START;
+
+        panel.add(colorspaceLabelPanel, gbc);
+
+        gbc.gridy = 2;
+        gbc.weighty=0.9;
+        gbc.weightx = 1;
+        gbc.fill = GridBagConstraints.BOTH;
+        gbc.anchor = GridBagConstraints.BELOW_BASELINE;
+
+        panel.add(box, gbc);
+    }
+
+    /**
+     * return the main panel that hold all the UI elements.
+     *
+     * @return JPanel instance
+     */
+    public Component getPanel()
+    {
+        return panel;
+    }
+
+    private int getHival(COSArray array)
+    {
+        int hival = ((COSNumber) array.getObject(2).getCOSObject()).intValue();
+        return Math.min(hival, 255);
+    }
+}

Propchange: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/CSIndexed.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/CSSeparation.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/CSSeparation.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/CSSeparation.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/CSSeparation.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,272 @@
+/*
+ * 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.pdfbox.tools.pdfdebugger.colorpane;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.IOException;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import javax.swing.BoxLayout;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JSlider;
+import javax.swing.JTextField;
+import javax.swing.border.BevelBorder;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import org.apache.pdfbox.cos.COSArray;
+import org.apache.pdfbox.pdmodel.graphics.color.PDSeparation;
+
+/**
+ * @author Khyrul Bashar.
+ */
+
+/**
+ *A class that provides the necessary UI and functionalities to show the Separation color space.
+ */
+public class CSSeparation implements ChangeListener, ActionListener
+{
+    private JSlider slider;
+    private JTextField tintField;
+    private JLabel colorBar;
+    private JPanel panel;
+
+    private PDSeparation separation;
+    private float tintValue = 1;
+
+    /**
+     * Constructor
+     * @param array COSArray instance of the separation color space.
+     */
+    public CSSeparation(COSArray array)
+    {
+        try
+        {
+            separation = new PDSeparation(array);
+        }
+        catch (IOException e)
+        {
+            throw new RuntimeException(e);
+        }
+        initUI();
+        initValues();
+    }
+
+    /**
+     * initialize all the UI elements and arrange them.
+     */
+    private void initUI()
+    {
+        Font boldFont = new Font(Font.MONOSPACED, Font.BOLD, 20);
+
+        GridBagConstraints gbc = new GridBagConstraints();
+        gbc.insets = new Insets(2, 2, 2, 2);
+        
+        JPanel inputPanel = new JPanel(new GridBagLayout());
+
+        slider = new JSlider(0, 100, 50);
+        slider.setMajorTickSpacing(50);
+        slider.setPaintTicks(true);
+
+        Dictionary labelTable = new Hashtable();
+        JLabel lightest = new JLabel("lightest");
+        lightest.setFont(new Font(Font.MONOSPACED, Font.BOLD, 10));
+        JLabel darkest = new JLabel("darkest");
+        darkest.setFont(new Font(Font.MONOSPACED, Font.BOLD, 10));
+        JLabel midPoint = new JLabel("0.5");
+        midPoint.setFont(new Font(Font.MONOSPACED, Font.BOLD, 10));
+        labelTable.put(0, lightest);
+        labelTable.put(50, midPoint);
+        labelTable.put(100, darkest);
+
+        slider.setPaintLabels(true);
+        slider.setLabelTable(labelTable);
+        slider.addChangeListener(this);
+
+        gbc.gridx = 0;
+        gbc.gridy = 0;
+        gbc.gridwidth = 10;
+        gbc.weightx = 1;
+        gbc.fill = GridBagConstraints.HORIZONTAL;
+        inputPanel.add(slider, gbc);
+
+        JLabel tintLabel = new JLabel("Tint Value:");
+        tintLabel.setFont(boldFont);
+        gbc.gridx = 0;
+        gbc.gridy = 1;
+        gbc.weightx = 0.5;
+        gbc.gridwidth = 1;
+        gbc.fill = GridBagConstraints.HORIZONTAL;
+        inputPanel.add(tintLabel, gbc);
+
+        tintField = new JTextField();
+        tintField.addActionListener(this);
+        tintField.setPreferredSize(new Dimension(10, 30));
+        gbc.gridx = 1;
+        gbc.weightx = 0.5;
+        gbc.gridwidth = 1;
+        gbc.fill = GridBagConstraints.HORIZONTAL;
+        inputPanel.add(tintField, gbc);
+
+        JPanel contentPanel = new JPanel(new GridBagLayout());
+        GridBagConstraints gbc2 = new GridBagConstraints();
+        gbc2.gridx = 0;
+        gbc2.gridy = 0;
+        gbc2.gridwidth = 2;
+        gbc2.weightx = 0.3;
+        gbc2.weighty = 1;
+        gbc2.fill = GridBagConstraints.HORIZONTAL;
+        contentPanel.add(inputPanel, gbc2);
+
+        colorBar = new JLabel();
+        colorBar.setOpaque(true);
+        gbc2.gridx = 2;
+        gbc2.weightx = 0.7;
+        gbc2.gridwidth = 4;
+        gbc2.gridheight = 2;
+        gbc2.fill = GridBagConstraints.BOTH;
+        contentPanel.add(colorBar, gbc2);
+        setColorBarBorder();
+
+        JPanel mainpanel = new JPanel(new GridBagLayout());
+
+        JLabel colorantNameLabel = new JLabel("Colorant: " + separation.getColorantName());
+        colorantNameLabel.setFont(boldFont);
+
+        GridBagConstraints maingbc = new GridBagConstraints();
+        maingbc.gridx = 0;
+        maingbc.gridy = 0;
+        maingbc.weightx = 1;
+        maingbc.weighty = 0.03;
+        maingbc.anchor = GridBagConstraints.FIRST_LINE_START;
+        mainpanel.add(colorantNameLabel, maingbc);
+
+        maingbc.gridx = 0;
+        maingbc.gridy = 1;
+        maingbc.weighty = 0.97;
+        maingbc.gridwidth = 10;
+        maingbc.fill = GridBagConstraints.HORIZONTAL;
+        mainpanel.add(contentPanel, maingbc);
+
+        panel = new JPanel();
+        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
+        panel.setPreferredSize(new Dimension(300, 500));
+
+        JLabel colorSpaceLabel = new JLabel("Separation colorspace");
+        colorSpaceLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
+        colorSpaceLabel.setFont(new Font(Font.MONOSPACED, Font.BOLD, 30));
+
+        panel.add(colorSpaceLabel);
+        panel.add(mainpanel);
+    }
+
+    private void initValues()
+    {
+        slider.setValue(getIntRepresentation(tintValue));
+        tintField.setText(Float.toString(tintValue));
+    }
+
+    /**
+     * return the main panel that hold all the UI elements.
+     * @return JPanel instance
+     */
+    public JPanel getPanel()
+    {
+        return panel;
+    }
+
+    /**
+     * input changed in slider.
+     * @param changeEvent
+     */
+    @Override
+    public void stateChanged(ChangeEvent changeEvent)
+    {
+            int value = slider.getValue();
+            tintValue = getFloatRepresentation(value);
+            tintField.setText(Float.toString(tintValue));
+            updateColorBar();
+    }
+
+    /**
+     * input changed in text field.
+     * @param actionEvent
+     */
+    @Override
+    public void actionPerformed(ActionEvent actionEvent)
+    {
+        String input = tintField.getText();
+        try
+        {
+            tintValue= Float.parseFloat(input);
+            slider.setValue(getIntRepresentation(tintValue));
+            updateColorBar();
+        }
+        catch (NumberFormatException e)
+        {
+            tintField.setText(Float.toString(tintValue));
+        }
+    }
+
+    private void updateColorBar()
+    {
+        try
+        {
+            float[] rgbValues = separation.toRGB(new float[] {tintValue});
+            colorBar.setBackground(new Color(rgbValues[0], rgbValues[1], rgbValues[2]));
+        }
+        catch (IOException e)
+        {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Set a little border around colorbar. color of the border is the darkest of the colorant.
+     */
+    private void setColorBarBorder()
+    {
+        try
+        {
+            float[] rgbValues = separation.toRGB(new float[] {1});
+            Color darkest= new Color(rgbValues[0], rgbValues[1], rgbValues[2]);
+            colorBar.setBorder(new BevelBorder(BevelBorder.LOWERED, darkest, darkest));
+        }
+        catch (IOException e)
+        {
+           throw new RuntimeException(e);
+        }
+    }
+
+    private float getFloatRepresentation(int value)
+    {
+        return (float) value/100;
+    }
+
+    private int getIntRepresentation(float value)
+    {
+        return (int) (value*100);
+    }
+}

Propchange: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/CSSeparation.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/ColorBarCellRenderer.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/ColorBarCellRenderer.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/ColorBarCellRenderer.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/ColorBarCellRenderer.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,43 @@
+/*
+ * 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.pdfbox.tools.pdfdebugger.colorpane;
+
+import java.awt.Color;
+import java.awt.Component;
+import javax.swing.JLabel;
+import javax.swing.JTable;
+import javax.swing.table.TableCellRenderer;
+
+/**
+ * @author Khyrul Bashar.
+ */
+
+/**
+ * ColorBarCellRenderer class that says how to render color bar columns
+ */
+public class ColorBarCellRenderer implements TableCellRenderer
+{
+    @Override
+    public Component getTableCellRendererComponent(
+            JTable jTable, Object o, boolean b, boolean b2, int i, int i2)
+    {
+        JLabel colorBar = new JLabel();
+        colorBar.setOpaque(true);
+        colorBar.setBackground((Color) o);
+        return colorBar;
+    }
+}

Propchange: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/ColorBarCellRenderer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/DeviceNColorant.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/DeviceNColorant.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/DeviceNColorant.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/DeviceNColorant.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,66 @@
+/*
+ * 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.pdfbox.tools.pdfdebugger.colorpane;
+
+import java.awt.Color;
+
+/**
+ * @author Khyrul Bashar.
+ */
+public class DeviceNColorant
+{
+    private String name;
+    private Color maximum;
+    private Color minimum;
+
+    /**
+     * Constructor
+     */
+    public DeviceNColorant()
+    {
+    }
+
+    public String getName()
+    {
+        return name;
+    }
+
+    public void setName(String name)
+    {
+        this.name = name;
+    }
+
+    public Color getMaximum()
+    {
+        return maximum;
+    }
+
+    public void setMaximum(Color maximum)
+    {
+        this.maximum = maximum;
+    }
+
+    public Color getMinimum()
+    {
+        return minimum;
+    }
+
+    public void setMinimum(Color minimum)
+    {
+        this.minimum = minimum;
+    }
+}

Propchange: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/DeviceNColorant.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/DeviceNTableModel.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/DeviceNTableModel.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/DeviceNTableModel.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/DeviceNTableModel.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,91 @@
+/*
+ * 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.pdfbox.tools.pdfdebugger.colorpane;
+
+import java.awt.Color;
+import javax.swing.table.AbstractTableModel;
+
+/**
+ * @author Khyrul Bashar.
+ */
+
+/**
+ * This the table model for showing DeviceN color space which extends AbstractTableModel.
+ */
+public class DeviceNTableModel extends AbstractTableModel
+{
+    private static final String[] COLUMNNAMES = new String[] { "Colorant", "Maximum", "Minimum"};
+    private final DeviceNColorant[] data;
+
+    /**
+     * Constructor
+     * @param colorants array of DeviceNColorant
+     */
+    public DeviceNTableModel(DeviceNColorant[] colorants)
+    {
+        data = colorants;
+    }
+
+    @Override
+    public int getRowCount()
+    {
+        return data.length;
+    }
+
+    @Override
+    public int getColumnCount()
+    {
+        return COLUMNNAMES.length;
+    }
+
+    @Override
+    public Object getValueAt(int row, int column)
+    {
+        switch (column)
+        {
+            case 0:
+                return data[row].getName();
+            case 1:
+                return data[row].getMaximum();
+            case 2:
+                return data[row].getMinimum();
+            default:
+                return null;
+        }
+    }
+
+    @Override
+    public String getColumnName(int column)
+    {
+        return COLUMNNAMES[column];
+    }
+
+    @Override
+    public Class<?> getColumnClass(int columnIndex)
+    {
+        switch (columnIndex)
+        {
+            case 0:
+                return String.class;
+            case 1:
+            case 2:
+                return Color.class;
+            default:
+                return null;
+        }
+    }
+}

Propchange: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/DeviceNTableModel.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/IndexedColorant.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/IndexedColorant.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/IndexedColorant.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/IndexedColorant.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,69 @@
+/*
+ * 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.pdfbox.tools.pdfdebugger.colorpane;
+
+import java.awt.Color;
+
+/**
+ * @author Khyrul Bashar.
+ */
+
+/**
+ * Class to represent Colorant in Indexed color.
+ */
+public class IndexedColorant
+{
+    private int index;
+    private float[] rgbValues;
+
+    /**
+     * Constructor.
+     */
+    public IndexedColorant(){}
+
+    public int getIndex()
+    {
+        return index;
+    }
+
+    public void setIndex(int index)
+    {
+        this.index = index;
+    }
+
+    public void setRgbValues(float[] rgbValues)
+    {
+        this.rgbValues = rgbValues;
+    }
+
+    public Color getColor()
+    {
+        return new Color(rgbValues[0], rgbValues[1], rgbValues[2]);
+    }
+
+    public String getRGBValuesString()
+    {
+        StringBuilder builder = new StringBuilder();
+        for (float i: rgbValues)
+        {
+            builder.append((int)(i*255));
+            builder.append(", ");
+        }
+        builder.deleteCharAt(builder.lastIndexOf(","));
+        return builder.toString();
+    }
+}

Propchange: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/IndexedColorant.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/IndexedTableModel.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/IndexedTableModel.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/IndexedTableModel.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/IndexedTableModel.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,93 @@
+/*
+ * 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.pdfbox.tools.pdfdebugger.colorpane;
+
+import java.awt.Color;
+import javax.swing.table.AbstractTableModel;
+
+/**
+ * @author Khyrul Bashar.
+ */
+
+/**
+ * This the table model for showing Indexed color space which extends AbstractTableModel.
+ */
+public class IndexedTableModel extends AbstractTableModel
+{
+
+    private static final String[] COLUMNSNAMES = new String[] {"Index", "RGB value", "Color"};
+    private final IndexedColorant[] data;
+
+    /**
+     * Constructor
+     * @param colorants array of IndexedColorant
+     */
+    public IndexedTableModel(IndexedColorant[] colorants)
+    {
+        data = colorants;
+    }
+
+    @Override
+    public int getRowCount()
+    {
+        return data.length;
+    }
+
+    @Override
+    public int getColumnCount()
+    {
+        return COLUMNSNAMES.length;
+    }
+
+    @Override
+    public Object getValueAt(int row, int column)
+    {
+        switch (column)
+        {
+            case 0:
+                return data[row].getIndex();
+            case 1:
+                return data[row].getRGBValuesString();
+            case 2:
+                return data[row].getColor();
+            default:
+                return null;
+        }
+    }
+
+    @Override
+    public String getColumnName(int column)
+    {
+        return COLUMNSNAMES[column];
+    }
+
+    @Override
+    public Class<?> getColumnClass(int columnIndex)
+    {
+        switch (columnIndex)
+        {
+            case 0:
+                return Integer.class;
+            case 1:
+                return String.class;
+            case 2:
+                return Color.class;
+            default:
+                return null;
+        }
+    }
+}

Propchange: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/IndexedTableModel.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/flagbitspane/AnnotFlag.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/flagbitspane/AnnotFlag.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/flagbitspane/AnnotFlag.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/flagbitspane/AnnotFlag.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,73 @@
+/*
+ *   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.pdfbox.tools.pdfdebugger.flagbitspane;
+
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation;
+
+/**
+ * @author Khyrul Bashar
+ *
+ * A class that provides Annotation flag bits.
+ */
+class AnnotFlag extends Flag
+{
+    private final COSDictionary annotDictionary;
+
+    /**
+     * Constructor
+     * @param annotDictionary COSDictionary instance
+     */
+    AnnotFlag(COSDictionary annotDictionary)
+    {
+        this.annotDictionary = annotDictionary;
+    }
+
+    @Override
+    String getFlagType()
+    {
+        return "Annot flag";
+    }
+
+    @Override
+    String getFlagValue()
+    {
+        return "Flag value: " + annotDictionary.getInt(COSName.F);
+    }
+
+    @Override
+    Object[][] getFlagBits()
+    {
+        PDAnnotation annotation = new PDAnnotation(annotDictionary)
+        {
+        };
+        return new Object[][]{
+                new Object[]{1, "Invisible", annotation.isInvisible()},
+                new Object[]{2, "Hidden", annotation.isHidden()},
+                new Object[]{3, "Print", annotation.isPrinted()},
+                new Object[]{4, "NoZoom", annotation.isNoZoom()},
+                new Object[]{5, "NoRotate", annotation.isNoRotate()},
+                new Object[]{6, "NoView", annotation.isNoView()},
+                new Object[]{7, "ReadOnly", annotation.isReadOnly()},
+                new Object[]{8, "Locked", annotation.isLocked()},
+                new Object[]{9, "ToggleNoView", annotation.isToggleNoView()},
+                new Object[]{10, "LockedContents", annotation.isLocked()}
+        };
+    }
+}

Propchange: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/flagbitspane/AnnotFlag.java
------------------------------------------------------------------------------
    svn:eol-style = native