pdfbox-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From le...@apache.org
Subject svn commit: r1705561 [4/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...
Date Sun, 27 Sep 2015 18:04:44 GMT
Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/HexPane.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/HexPane.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/HexPane.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/HexPane.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,387 @@
+/*
+ * 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.hexviewer;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Point;
+import java.awt.Rectangle;
+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 java.awt.font.TextAttribute;
+import java.text.AttributedString;
+import java.util.ArrayList;
+import java.util.List;
+import javax.swing.JPanel;
+
+/**
+ * @author Khyrul Bashar
+ *
+ * HexPane shows the byte in a Grid table where every row has 16 bytes. It only draws bytes those are
+ * only visible at a given time.
+ */
+class HexPane extends JPanel implements KeyListener, MouseListener, MouseMotionListener, HexModelChangeListener
+{
+    private final HexModel model;
+    private int selectedIndex = -1;
+    private static final byte EDIT = 2;
+    private static final byte SELECTED = 1;
+    private static final byte NORMAL = 0;
+
+    private byte state = NORMAL;
+    private int selectedChar = 0;
+
+    private final List<HexChangeListener> hexChangeListeners = new ArrayList<HexChangeListener>();
+    private final List<SelectionChangeListener> selectionChangeListeners = new ArrayList<SelectionChangeListener>();
+
+    /**
+     * Constructor.
+     * @param model HexModel instance.
+     */
+    HexPane(HexModel model)
+    {
+        this.model = model;
+        model.addHexModelChangeListener(this);
+        setPreferredSize(new Dimension(HexView.HEX_PANE_WIDTH, HexView.CHAR_HEIGHT * (model.totalLine()+1)));
+        this.addMouseListener(this);
+        this.addMouseMotionListener(this);
+        this.addKeyListener(this);
+        setAutoscrolls(true);
+        setFont(HexView.FONT);
+    }
+
+    @Override
+    protected void paintComponent(Graphics g)
+    {
+        super.paintComponent(g);
+
+        Graphics2D g2d = (Graphics2D)g;
+        g2d.setRenderingHints(HexView.RENDERING_HINTS);
+        
+        Rectangle bound = getVisibleRect();
+        g.clearRect(bound.x, bound.y, bound.width, bound.height);
+        g.setColor(Color.WHITE);
+        g.fillRect(bound.x, bound.y, bound.width, bound.height);
+
+        int x = HexView.LINE_INSET;
+        int y = bound.y;
+        if (y == 0 || y% HexView.CHAR_HEIGHT != 0)
+        {
+            y += HexView.CHAR_HEIGHT - y% HexView.CHAR_HEIGHT;
+        }
+        int firstLine = y/ HexView.CHAR_HEIGHT;
+
+        g.setColor(Color.BLACK);
+        for (int i = firstLine; i <= firstLine + bound.height/ HexView.CHAR_HEIGHT; i++)
+        {
+            if (i > model.totalLine())
+            {
+                break;
+            }
+            byte[] bytes = model.getBytesForLine(i);
+            int index = (i - 1) * 16;
+            for (byte by : bytes)
+            {
+                String str = String.format("%02X", by);
+                if (selectedIndex == index && state == SELECTED)
+                {
+                    g.drawString(getSelectedString(str).getIterator(), x, y);
+                }
+                else if (selectedIndex == index && state == EDIT)
+                {
+                    paintInEdit(g, by, x, y);
+                }
+                else
+                {
+                    g.drawString(str, x, y);
+                }
+                x += HexView.CHAR_WIDTH;
+                index++;
+            }
+            x = HexView.LINE_INSET;
+            y += HexView.CHAR_HEIGHT;
+        }
+    }
+
+    private void paintInEdit(Graphics g, byte content, int x, int y)
+    {
+        g.setFont(HexView.BOLD_FONT);
+        g.setColor(Color.white);
+
+        char[] chars = getChars(content);
+
+        if (selectedChar == 0)
+        {
+            g.setColor(HexView.SELECTED_COLOR);
+            g.drawChars(chars, 0, 1, x, y);
+
+            g.setColor(Color.black);
+            g.drawChars(chars, 1, 1, x + g.getFontMetrics().charWidth(chars[0]), y);
+        }
+        else
+        {
+            g.setColor(Color.black);
+            g.drawChars(chars, 0, 1, x, y);
+
+            g.setColor(HexView.SELECTED_COLOR);
+            g.drawChars(chars, 1, 1,x + g.getFontMetrics().charWidth(chars[0]), y);
+        }
+        setDefault(g);
+    }
+
+    private AttributedString getSelectedString(String str)
+    {
+        AttributedString string = new AttributedString(str);
+        string.addAttribute(TextAttribute.FONT, HexView.BOLD_FONT);
+        string.addAttribute(TextAttribute.FOREGROUND, HexView.SELECTED_COLOR);
+        return string;
+    }
+
+    private void setDefault(Graphics g)
+    {
+        g.setColor(Color.black);
+        g.setFont(this.getFont());
+    }
+
+    /**
+     * Returns the index for a given point If there is any byte in there.
+     * @param point Point instance.
+     * @return index.
+     */
+    private int getIndexForPoint(Point point)
+    {
+        if (point.x <= 20 || point.x >= (16 * HexView.CHAR_WIDTH)+20 )
+        {
+            return -1;
+        }
+        int y = point.y;
+        int lineNumber = (y+ (HexView.CHAR_HEIGHT -(y % HexView.CHAR_HEIGHT)))/ HexView.CHAR_HEIGHT;
+        int x = point.x - 20;
+        int elementNumber = (x / HexView.CHAR_WIDTH);
+        return  (lineNumber-1) * 16 + elementNumber;
+    }
+
+    /**
+     * Returns the starting point in the view for any index.
+     * @param index int.
+     * @return Point instance.
+     */
+    private Point getPointForIndex(int index)
+    {
+        int x = HexView.LINE_INSET + HexModel.elementIndexInLine(index)* HexView.CHAR_WIDTH;
+        int y = HexModel.lineNumber(index) * HexView.CHAR_HEIGHT;
+        return new Point(x, y);
+    }
+
+    /**
+     * Puts an index in selected state or in other word it selects the byte of the index.
+     * @param index
+     */
+    private void putInSelected(int index)
+    {
+        state = SELECTED;
+        selectedChar = 0;
+        Point point = getPointForIndex(index);
+        //for column one
+        if (index%16 == 0)
+        {
+            scrollRectToVisible(new Rectangle(0, HexModel.lineNumber(index) * HexView.CHAR_HEIGHT, 1, 1));
+        }
+        else if (!getVisibleRect().intersects(point.x, point.y, HexView.CHAR_WIDTH, HexView.CHAR_HEIGHT))
+        {
+            scrollRectToVisible(new Rectangle(point.x, point.y, HexView.CHAR_WIDTH, HexView.CHAR_HEIGHT));
+        }
+        selectedIndex = index;
+        repaint();
+        requestFocusInWindow();
+    }
+
+    private void fireSelectionChanged(SelectEvent event)
+    {
+        for (SelectionChangeListener listener:selectionChangeListeners)
+        {
+            listener.selectionChanged(event);
+        }
+    }
+
+    private void fireHexValueChanged(byte value, int index)
+    {
+        for (HexChangeListener listener:hexChangeListeners)
+        {
+            listener.hexChanged(new HexChangedEvent(value, index));
+        }
+    }
+
+    public void addSelectionChangeListener(SelectionChangeListener listener)
+    {
+        selectionChangeListeners.add(listener);
+    }
+
+    public void addHexChangeListeners(HexChangeListener listener)
+    {
+        hexChangeListeners.add(listener);
+    }
+
+    @Override
+    public void keyTyped(KeyEvent keyEvent)
+    {
+        if (selectedIndex != -1)
+        {
+            char c = keyEvent.getKeyChar();
+            if (isHexChar(c))
+            {
+                byte previousByte = model.getByte(selectedIndex);
+                char[] chars = getChars(previousByte);
+                chars[selectedChar] = c;
+                byte editByte = getByte(chars);
+                if (selectedChar == 0)
+                {
+                    state = EDIT;
+                    selectedChar = 1;
+                    fireHexValueChanged(editByte, selectedIndex);
+                }
+                else
+                {
+                    fireHexValueChanged(editByte, selectedIndex);
+                    fireSelectionChanged(new SelectEvent(selectedIndex, SelectEvent.NEXT));
+                }
+            }
+        }
+    }
+
+    @Override
+    public void keyPressed(KeyEvent keyEvent)
+    {
+        if (state == SELECTED || state == EDIT)
+        {
+            switch (keyEvent.getKeyCode())
+            {
+                case 37:
+                    if (state == EDIT && selectedChar == 1)
+                    {
+                        selectedChar = 0;
+                        repaint();
+                    }
+                    else
+                    {
+                        fireSelectionChanged(new SelectEvent(selectedIndex, SelectEvent.PREVIOUS));
+                    }
+                    break;
+                case 39:
+                    fireSelectionChanged(new SelectEvent(selectedIndex, SelectEvent.NEXT));
+                    break;
+                case 38:
+                    fireSelectionChanged(new SelectEvent(selectedIndex, SelectEvent.UP));
+                    break;
+                case 40:
+                    fireSelectionChanged(new SelectEvent(selectedIndex, SelectEvent.DOWN));
+                    break;
+                default:
+                    break;
+            }
+        }
+    }
+
+
+    @Override
+    public void keyReleased(KeyEvent keyEvent)
+    {
+
+    }
+
+    @Override
+    public void mouseClicked(MouseEvent mouseEvent)
+    {
+        int index = getIndexForPoint(mouseEvent.getPoint());
+        if (index == -1)
+        {
+            fireSelectionChanged(new SelectEvent(-1, SelectEvent.NONE));
+            return;
+        }
+        fireSelectionChanged(new SelectEvent(index, SelectEvent.IN));
+    }
+
+    @Override
+    public void mousePressed(MouseEvent mouseEvent)
+    {
+
+    }
+
+    @Override
+    public void mouseReleased(MouseEvent mouseEvent)
+    {
+    }
+
+    @Override
+    public void mouseEntered(MouseEvent mouseEvent)
+    {
+
+    }
+
+    @Override
+    public void mouseExited(MouseEvent mouseEvent)
+    {
+
+    }
+
+    @Override
+    public void mouseDragged(MouseEvent mouseEvent)
+    {
+
+    }
+
+    @Override
+    public void mouseMoved(MouseEvent mouseEvent)
+    {
+
+    }
+
+    private static boolean isHexChar(char c)
+    {
+        return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
+    }
+
+    private char[] getChars(byte b)
+    {
+        return String.format("%02X", b & 0XFF).toCharArray();
+    }
+
+    private byte getByte(char[] chars)
+    {
+        return (byte) (Integer.parseInt(new String(chars), 16) & 0XFF);
+    }
+
+    public void setSelected(int index)
+    {
+        if (index != selectedIndex)
+        {
+            putInSelected(index);
+        }
+    }
+
+    @Override
+    public void hexModelChanged(HexModelChangedEvent event)
+    {
+        repaint();
+    }
+}

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

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/HexView.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/HexView.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/HexView.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/HexView.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,87 @@
+/*
+ * 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.hexviewer;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.RenderingHints;
+import java.util.HashMap;
+import java.util.Map;
+import javax.swing.JComponent;
+import javax.swing.JPanel;
+import javax.swing.UIManager;
+
+/**
+ * @author Khyrul Bashar
+ *
+ * HexView takes a byte array or Stream instance and shows them in Hex viewer.
+ */
+public class HexView
+{
+    private final JComponent mainPane;
+    
+    static final int FONT_SIZE = ((Font)UIManager.get("Label.font")).getSize();
+    static final Font FONT = new Font("monospaced", Font.PLAIN, FONT_SIZE);
+    static final int CHAR_HEIGHT = 20;
+    static final int CHAR_WIDTH = 35;
+    static final int LINE_INSET = 20;
+    static final Color SELECTED_COLOR = UIManager.getColor("textHighlight");
+    static final Font BOLD_FONT = new Font("monospaced", Font.BOLD, FONT_SIZE);
+    static final int HEX_PANE_WIDTH = 600;
+    static final int ADDRESS_PANE_WIDTH = 120;
+    static final int ASCII_PANE_WIDTH = 270;
+    static final int TOTAL_WIDTH = HEX_PANE_WIDTH + ADDRESS_PANE_WIDTH +ASCII_PANE_WIDTH;
+    static final Map<RenderingHints.Key, Object> RENDERING_HINTS = new HashMap<RenderingHints.Key, Object>();
+    static
+    {
+        RENDERING_HINTS.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+        RENDERING_HINTS.put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_GASP);
+    }
+
+    public HexView()
+    {
+        mainPane = new JPanel(new BorderLayout());
+    }
+
+    /**
+     * Constructor.
+     * @param bytes takes a byte array.
+     */
+    public HexView(byte[] bytes)
+    {
+        mainPane = new JPanel(new BorderLayout());
+        mainPane.add(new HexEditor(new HexModel(bytes)));
+    }
+
+    public void changeData(byte[] bytes)
+    {
+        if (mainPane.getComponentCount() > 0)
+        {
+            mainPane.removeAll();
+        }
+        HexModel model = new HexModel(bytes);
+        mainPane.add(new HexEditor(model));
+        mainPane.validate();
+    }
+
+    public JComponent getPane()
+    {
+        return mainPane;
+    }
+}

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

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/SelectEvent.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/SelectEvent.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/SelectEvent.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/SelectEvent.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,58 @@
+/*
+ * 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.hexviewer;
+
+/**
+ * @author Khyrul Bashar
+ *
+ * This describes any selection event happens in hex view
+ */
+class SelectEvent
+{
+    static final String NEXT = "next";
+    static final String PREVIOUS = "previous";
+    static final String UP = "up";
+    static final String DOWN= "down";
+    static final String NONE = "none";
+    static final String IN = "in";
+    static final String EDIT = "edit";
+
+    private final int hexIndex;
+    private final String navigation;
+
+    /**
+     * Constructor.
+     * @param ind index of present selection.
+     * @param nav Type of navigation.
+     */
+    SelectEvent(int ind, String nav)
+    {
+        hexIndex = ind;
+        navigation = nav;
+    }
+
+    public int getHexIndex()
+    {
+        return hexIndex;
+    }
+
+    public String getNavigation()
+    {
+        return navigation;
+    }
+}

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

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/SelectionChangeListener.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/SelectionChangeListener.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/SelectionChangeListener.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/SelectionChangeListener.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,26 @@
+/*
+ * 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.hexviewer;
+
+/**
+ * @author Khyrul Bashar
+ */
+interface SelectionChangeListener
+{
+    void selectionChanged(SelectEvent event);
+}

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

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/StatusPane.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/StatusPane.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/StatusPane.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/StatusPane.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,68 @@
+/*
+ * 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.hexviewer;
+
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+
+/**
+ * @author Khyrul Bashar
+ *
+ * This shows the currently selected bytes, index, line number and column number.
+ */
+class StatusPane extends JPanel
+{
+    private static final int HEIGHT = 20;
+    private JLabel lineLabel;
+    private JLabel colLabel;
+    private JLabel indexLabel;
+
+    StatusPane()
+    {
+        setLayout(new FlowLayout(FlowLayout.LEFT));
+        createView();
+    }
+
+    private void createView()
+    {
+        JLabel line = new JLabel("Line:");
+        JLabel column = new JLabel("Column:");
+        lineLabel = new JLabel("");
+        lineLabel.setPreferredSize(new Dimension(100, HEIGHT));
+        colLabel = new JLabel("");
+        colLabel.setPreferredSize(new Dimension(100, HEIGHT));
+        JLabel index = new JLabel("Index:");
+        indexLabel = new JLabel("");
+
+        add(line);
+        add(lineLabel);
+        add(column);
+        add(colLabel);
+        add(index);
+        add(indexLabel);
+    }
+
+    void updateStatus(int index)
+    {
+        lineLabel.setText(String.valueOf(HexModel.lineNumber(index)));
+        colLabel.setText(String.valueOf(HexModel.elementIndexInLine(index)+1));
+        indexLabel.setText(String.valueOf(index));
+    }
+}

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

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/UpperPane.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/UpperPane.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/UpperPane.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/UpperPane.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,65 @@
+/*
+ * 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.hexviewer;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import javax.swing.BorderFactory;
+import javax.swing.JPanel;
+
+/**
+ * @author Khyrul Bashar
+ *
+ * This class builds the upper banner in the hex view.
+ */
+class UpperPane extends JPanel
+{
+    UpperPane()
+    {
+        setFont(HexView.FONT);
+        setPreferredSize(new Dimension(HexView.TOTAL_WIDTH, 20));
+        setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, Color.LIGHT_GRAY));
+    }
+
+    @Override
+    protected void paintComponent(Graphics g)
+    {
+        super.paintComponent(g);
+        
+        Graphics2D g2d = (Graphics2D)g;
+        g2d.setRenderingHints(HexView.RENDERING_HINTS);
+        
+        int x = HexView.LINE_INSET-2;
+        int y = 16;
+
+        g.drawString("Offset", x, y);
+
+        x += HexView.ADDRESS_PANE_WIDTH + 2;
+
+        for (int i = 0; i <= 15; i++)
+        {
+            g.drawString(String.format("%02X", i), x, y);
+            x += HexView.CHAR_WIDTH;
+        }
+
+        x+=HexView.LINE_INSET*2;
+        g.drawString("Text", x, y);
+    }
+}

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

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/pagepane/PagePane.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/pagepane/PagePane.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/pagepane/PagePane.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/pagepane/PagePane.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,179 @@
+/*
+ * 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.pagepane;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Font;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.util.concurrent.ExecutionException;
+import javax.swing.BoxLayout;
+import javax.swing.ImageIcon;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.SwingWorker;
+import javax.swing.event.AncestorEvent;
+import javax.swing.event.AncestorListener;
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.PDPage;
+import org.apache.pdfbox.rendering.PDFRenderer;
+import org.apache.pdfbox.tools.pdfdebugger.ui.RotationMenu;
+import org.apache.pdfbox.tools.pdfdebugger.ui.ZoomMenu;
+import org.apache.pdfbox.tools.util.ImageUtil;
+
+/**
+ * Display the page number and a page rendering.
+ * 
+ * @author Tilman Hausherr
+ * @author John Hewson
+ */
+public class PagePane implements ActionListener, AncestorListener
+{
+    private JPanel panel;
+    private int pageIndex = -1;
+    private final PDDocument document;
+    private JLabel label;
+    private ZoomMenu zoomMenu;
+    private RotationMenu rotationMenu;
+
+    public PagePane(PDDocument document, COSDictionary page)
+    {
+        PDPage pdPage = new PDPage(page);
+        pageIndex = document.getPages().indexOf(pdPage);
+        this.document = document;
+        initUI();
+    }
+
+    private void initUI()
+    {
+        panel = new JPanel();
+        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
+
+        String pageLabelText = pageIndex < 0 ? "Page number not found" : "Page " + (pageIndex + 1);
+        
+        JLabel pageLabel = new JLabel(pageLabelText);
+        pageLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
+        pageLabel.setFont(new Font(Font.MONOSPACED, Font.BOLD, 30));
+        pageLabel.setBackground(Color.GREEN);
+        panel.add(pageLabel);
+        
+        label = new JLabel();
+        label.setBackground(panel.getBackground());
+        label.setAlignmentX(Component.CENTER_ALIGNMENT);
+        panel.add(label);
+        panel.addAncestorListener(this);
+
+        // render in a background thread: rendering is read-only, so this should be ok, despite
+        // the fact that PDDocument is not officially thread safe
+        new RenderWorker(1, 0).execute();
+    }
+
+    /**
+     * Returns the main panel that hold all the UI elements.
+     *
+     * @return JPanel instance
+     */
+    public Component getPanel()
+    {
+        return panel;
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent actionEvent)
+    {
+        String actionCommand = actionEvent.getActionCommand();
+        if (ZoomMenu.isZoomMenu(actionCommand) || RotationMenu.isRotationMenu(actionCommand))
+        {
+            new RenderWorker(ZoomMenu.getZoomScale(), RotationMenu.getRotationDegrees()).execute();
+        }
+    }
+
+    @Override
+    public void ancestorAdded(AncestorEvent ancestorEvent)
+    {
+        zoomMenu = ZoomMenu.getInstance();
+        zoomMenu.addMenuListeners(this);
+        zoomMenu.setZoomSelection(ZoomMenu.ZOOM_100_PERCENT);
+        zoomMenu.setEnableMenu(true);
+        
+        rotationMenu = RotationMenu.getInstance();
+        rotationMenu.addMenuListeners(this);
+        rotationMenu.setRotationSelection(RotationMenu.ROTATE_0_DEGREES);
+        rotationMenu.setEnableMenu(true);
+    }
+
+    @Override
+    public void ancestorRemoved(AncestorEvent ancestorEvent)
+    {
+        zoomMenu.setEnableMenu(false);
+        rotationMenu.setEnableMenu(false);
+    }
+
+    @Override
+    public void ancestorMoved(AncestorEvent ancestorEvent)
+    {
+    }
+
+    /**
+     * Note that PDDocument is not officially thread safe, caution advised.
+     */
+    private final class RenderWorker extends SwingWorker<BufferedImage, Integer>
+    {
+        private final float scale;
+        private final int rotation;
+
+        private RenderWorker(float scale, int rotation)
+        {
+            this.scale = scale;
+            this.rotation = rotation;
+        }
+
+        @Override
+        protected BufferedImage doInBackground() throws IOException
+        {
+            label.setIcon(null);
+            label.setText("Loading...");
+            PDFRenderer renderer = new PDFRenderer(document);
+            BufferedImage bim = renderer.renderImage(pageIndex, scale);
+            return ImageUtil.getRotatedImage(bim, rotation);
+        }
+
+        @Override
+        protected void done()
+        {
+            try
+            {
+                label.setIcon(new ImageIcon(get()));
+                label.setText(null);
+            }
+            catch (InterruptedException e)
+            {
+                label.setText(e.getMessage());
+                throw new RuntimeException(e);
+            }
+            catch (ExecutionException e)
+            {
+                label.setText(e.getMessage());
+                throw new RuntimeException(e);
+            }
+        }
+    }
+}

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

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/OperatorMarker.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/OperatorMarker.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/OperatorMarker.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/OperatorMarker.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.streampane;
+
+import java.awt.Color;
+import java.util.HashMap;
+import java.util.Map;
+import javax.swing.text.Style;
+import javax.swing.text.StyleConstants;
+import javax.swing.text.StyleContext;
+
+/**
+ * @author Khyrul Bashar
+ */
+final class OperatorMarker
+{
+    public static final String BEGIN_TEXT_OBJECT = "BT";
+    public static final String END_TEXT_OBJECT = "ET";
+    public static final String SAVE_GRAPHICS_STATE = "q";
+    public static final String RESTORE_GRAPHICS_STATE = "Q";
+    public static final String CONCAT = "cm";
+    public static final String INLINE_IMAGE_BEGIN = "BI";
+    public static final String IMAGE_DATA = "ID";
+    public static final String INLINE_IMAGE_END = "EI";
+
+    private static final Map<String, Style> operatorStyleMap;
+
+    static
+    {
+        StyleContext styleContext = StyleContext.getDefaultStyleContext();
+
+        Style common = styleContext.addStyle("common", null);
+        StyleConstants.setBold(common, true);
+
+        Style textObjectStyle = styleContext.addStyle("text_object", common);
+        StyleConstants.setForeground(textObjectStyle, new Color(0, 100, 0));
+
+        Style graphicsStyle = styleContext.addStyle("graphics", common);
+        StyleConstants.setForeground(graphicsStyle, new Color(255, 68, 68));
+
+        Style concatStyle = styleContext.addStyle("cm", common);
+        StyleConstants.setForeground(concatStyle, new Color(1, 169, 219));
+
+        Style inlineImage = styleContext.addStyle("inline_image", common);
+        StyleConstants.setForeground(inlineImage, new Color(71, 117, 163));
+
+        Style imageData = styleContext.addStyle("ID", common);
+        StyleConstants.setForeground(imageData, new Color(255, 165, 0));
+
+        Map<String, Style> styleMap = new HashMap<String, Style>();
+
+        styleMap.put(BEGIN_TEXT_OBJECT, textObjectStyle);
+        styleMap.put(END_TEXT_OBJECT, textObjectStyle);
+        styleMap.put(SAVE_GRAPHICS_STATE, graphicsStyle);
+        styleMap.put(RESTORE_GRAPHICS_STATE, graphicsStyle);
+        styleMap.put(CONCAT, concatStyle);
+        styleMap.put(INLINE_IMAGE_BEGIN, inlineImage);
+        styleMap.put(IMAGE_DATA, imageData);
+        styleMap.put(INLINE_IMAGE_END, inlineImage);
+
+        operatorStyleMap = styleMap;
+    }
+
+    private OperatorMarker()
+    {
+    }
+
+    public static Style getStyle(String operator)
+    {
+        if (operatorStyleMap.containsKey(operator))
+        {
+            return operatorStyleMap.get(operator);
+        }
+        return null;
+    }
+}

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

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/Stream.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/Stream.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/Stream.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/Stream.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,232 @@
+/*
+ * 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.streampane;
+
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.pdfbox.cos.COSArray;
+import org.apache.pdfbox.cos.COSBase;
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.cos.COSStream;
+import org.apache.pdfbox.pdmodel.PDResources;
+import org.apache.pdfbox.pdmodel.common.PDStream;
+import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
+
+/**
+ * @author Khyrul Bashar
+ *
+ * A class that provides the COSStream in different version and related informations.
+ */
+public class Stream
+{
+    public static final String UNFILTERED = "Unfiltered";
+    public static final String IMAGE = "Image";
+
+    private final COSStream stream;
+    private final boolean isThumb;
+    private final boolean isImage;
+    private final Map<String, List<String>> filters;
+
+    /**
+     * Constructor.
+     *
+     * @param cosStream COSStream instance.
+     * @param isThumb boolean instance says if the stream is thumbnail image.
+     */
+    Stream(COSStream cosStream, boolean isThumb)
+    {
+        this.stream = cosStream;
+        this.isThumb = isThumb;
+        this.isImage = isImageStream(cosStream, isThumb);
+
+        filters = createFilterList(cosStream);
+    }
+
+    /**
+     * Return if this is stream is an Image XObject.
+     *
+     * @return true if this an image and false otherwise.
+     */
+    public boolean isImage()
+    {
+        return isImage;
+    }
+
+    /**
+     * Return the available filter list. Only "Unfiltered" is returned if there is no filter and in
+     * case of XObject image type stream "Image" is also included in the list.
+     *
+     * @return An array of String.
+     */
+    public List<String> getFilterList()
+    {
+        List<String> list = new ArrayList<String>();
+        for (Map.Entry<String, List<String>> entry : filters.entrySet())
+        {
+            list.add(entry.getKey());
+        }
+        return list;
+    }
+
+    /**
+     * Returns the label for the "Unfiltered" menu item.
+     */
+    private String getFilteredLabel()
+    {
+        StringBuilder sb = new StringBuilder();
+        COSBase base = stream.getFilters();
+        if (base instanceof COSName)
+        {
+            sb.append(((COSName) base).getName());
+        }
+        else if (base instanceof COSArray)
+        {
+            COSArray filterArray = (COSArray) base;
+            for (int i = 0; i < filterArray.size(); i++)
+            {
+                if (i > 0)
+                {
+                    sb.append(", ");
+                }
+                sb.append(((COSName) filterArray.get(i)).getName());
+            }
+        }
+        return "Filtered (" + sb.toString() + ")";
+    }
+
+    /**
+     * Returns a InputStream of a partially filtered stream.
+     *
+     * @param key is an instance of String which tells which version of stream should be returned.
+     * @return an InputStream.
+     */
+    public InputStream getStream(String key)
+    {
+        try
+        {
+            if (UNFILTERED.equals(key))
+            {
+                return stream.createInputStream();
+            }
+            else if (getFilteredLabel().equals(key))
+            {
+                return stream.createRawInputStream();
+            }
+            else
+            {
+                return new PDStream(stream).createInputStream(filters.get(key));
+            }
+        }
+        catch (IOException e)
+        {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    /**
+     * Provide the image for stream. The stream must be image XObject.
+     *
+     * @param resources PDResources for the XObject.
+     * @return A BufferedImage.
+     */
+    public BufferedImage getImage(PDResources resources)
+    {
+        try
+        {
+            PDImageXObject imageXObject;
+            if (isThumb)
+            {
+                imageXObject = PDImageXObject.createThumbnail(stream);
+            }
+            else
+            {
+                imageXObject = new PDImageXObject(new PDStream(stream), resources);
+            }
+            return imageXObject.getImage();
+        }
+        catch (IOException e)
+        {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    private Map<String, List<String>> createFilterList(COSStream stream)
+    {
+        Map<String, List<String>> filterList = new LinkedHashMap<String, List<String>>();
+
+        if (isImage)
+        {
+            filterList.put(IMAGE, null);
+        }
+
+        filterList.put(UNFILTERED, null);
+        PDStream pdStream = new PDStream(stream);
+
+        if (pdStream.getFilters() != null)
+        {
+            int filtersSize = pdStream.getFilters().size();
+
+            for (int i = filtersSize - 1; i >= 1; i--)
+            {
+                filterList.put(getPartialStreamCommand(i), getStopFilterList(i));
+            }
+            filterList.put(getFilteredLabel(), null);
+        }
+        return filterList;
+    }
+
+    private String getPartialStreamCommand(final int indexOfStopFilter)
+    {
+        List<COSName> avaiablrFilters = new PDStream(stream).getFilters();
+
+        StringBuilder nameListBuilder = new StringBuilder();
+        for (int i = indexOfStopFilter; i < avaiablrFilters.size(); i++)
+        {
+            nameListBuilder.append(avaiablrFilters.get(i).getName()).append(" & ");
+        }
+        nameListBuilder.delete(nameListBuilder.lastIndexOf("&"), nameListBuilder.length());
+
+        return "Keep " + nameListBuilder.toString() + "...";
+    }
+
+    private List<String> getStopFilterList(final int stopFilterIndex)
+    {
+        List<COSName> avaiablrFilters = new PDStream(stream).getFilters();
+
+        final List<String> stopFilters = new ArrayList<String>(1);
+        stopFilters.add(avaiablrFilters.get(stopFilterIndex).getName());
+
+        return stopFilters;
+    }
+
+    private boolean isImageStream(COSDictionary dic, boolean isThumb)
+    {
+        if (isThumb)
+        {
+            return true;
+        }
+        return dic.containsKey(COSName.SUBTYPE) && dic.getCOSName(COSName.SUBTYPE).equals(COSName.IMAGE);
+    }
+}

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

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/StreamImageView.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/StreamImageView.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/StreamImageView.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/StreamImageView.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,141 @@
+/*
+ * 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.streampane;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Image;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.image.BufferedImage;
+import javax.swing.Box;
+import javax.swing.BoxLayout;
+import javax.swing.ImageIcon;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.border.LineBorder;
+import javax.swing.event.AncestorEvent;
+import javax.swing.event.AncestorListener;
+import org.apache.pdfbox.tools.pdfdebugger.ui.RotationMenu;
+import org.apache.pdfbox.tools.pdfdebugger.ui.ZoomMenu;
+import org.apache.pdfbox.tools.util.ImageUtil;
+
+/**
+ * @author Khyrul Bashar
+ *
+ * A class that provides the container for the image in case of image showing in stream pane.
+ */
+class StreamImageView implements ActionListener, AncestorListener
+{
+    private final BufferedImage image;
+    private JScrollPane scrollPane;
+    private JLabel label;
+    private ZoomMenu zoomMenu;
+    private RotationMenu rotationMenu;
+
+    /**
+     * constructor.
+     * @param image instance of BufferedImage.
+     */
+    StreamImageView(BufferedImage image)
+    {
+        this.image = image;
+        initUI();
+    }
+
+    private void initUI()
+    {
+        JPanel panel = new JPanel();
+        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
+
+        label = new JLabel();
+        label.setBorder(new LineBorder(Color.BLACK));
+        label.setAlignmentX(Component.CENTER_ALIGNMENT);
+        label.setIcon(new ImageIcon(image));
+
+        panel.add(Box.createVerticalGlue());
+        panel.add(label);
+        panel.add(Box.createVerticalGlue());
+
+        scrollPane = new JScrollPane();
+        scrollPane.setPreferredSize(new Dimension(300, 400));
+        scrollPane.addAncestorListener(this);
+        scrollPane.setViewportView(panel);
+    }
+
+    /**
+     * Returns the view i.e container containing image.
+     * @return A JComponent instance.
+     */
+    JComponent getView()
+    {
+        return scrollPane;
+    }
+
+    private Image zoomImage(BufferedImage origin, float scale, int rotation)
+    {
+        BufferedImage rotatedImage = ImageUtil.getRotatedImage(origin, rotation);
+        int resizedWidth = (int) (rotatedImage.getWidth() * scale);
+        int resizedHeight = (int) (rotatedImage.getHeight() * scale);
+        return rotatedImage.getScaledInstance(resizedWidth, resizedHeight, BufferedImage.SCALE_SMOOTH);
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent actionEvent)
+    {
+        String actionCommand = actionEvent.getActionCommand();
+        if (ZoomMenu.isZoomMenu(actionCommand) || RotationMenu.isRotationMenu(actionCommand))
+        {
+            addImage(zoomImage(image, ZoomMenu.getZoomScale(), RotationMenu.getRotationDegrees()));
+        }
+    }
+
+    private void addImage(Image img)
+    {
+        label.setIcon(new ImageIcon(img));
+        label.revalidate();
+    }
+
+    @Override
+    public void ancestorAdded(AncestorEvent ancestorEvent)
+    {
+        zoomMenu = ZoomMenu.getInstance();
+        zoomMenu.addMenuListeners(this);
+        zoomMenu.setZoomSelection(ZoomMenu.ZOOM_100_PERCENT);
+        zoomMenu.setEnableMenu(true);
+        
+        rotationMenu = RotationMenu.getInstance();
+        rotationMenu.addMenuListeners(this);
+        rotationMenu.setRotationSelection(RotationMenu.ROTATE_0_DEGREES);
+        rotationMenu.setEnableMenu(true);
+    }
+
+    @Override
+    public void ancestorRemoved(AncestorEvent ancestorEvent)
+    {
+        zoomMenu.setEnableMenu(false);
+        rotationMenu.setEnableMenu(false);
+    }
+
+    @Override
+    public void ancestorMoved(AncestorEvent ancestorEvent)
+    {
+    }
+}

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

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/StreamPane.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/StreamPane.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/StreamPane.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/StreamPane.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,513 @@
+/*
+ * 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.streampane;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+import javax.imageio.ImageIO;
+import javax.swing.BoxLayout;
+import javax.swing.JComboBox;
+import javax.swing.JComponent;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JTabbedPane;
+import javax.swing.SwingWorker;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.DefaultStyledDocument;
+import javax.swing.text.Style;
+import javax.swing.text.StyleConstants;
+import javax.swing.text.StyleContext;
+import javax.swing.text.StyledDocument;
+import org.apache.pdfbox.contentstream.operator.Operator;
+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.COSName;
+import org.apache.pdfbox.cos.COSNumber;
+import org.apache.pdfbox.cos.COSStream;
+import org.apache.pdfbox.cos.COSString;
+import org.apache.pdfbox.io.IOUtils;
+import org.apache.pdfbox.pdfparser.PDFStreamParser;
+import org.apache.pdfbox.pdmodel.PDResources;
+import org.apache.pdfbox.tools.pdfdebugger.hexviewer.HexView;
+import org.apache.pdfbox.tools.pdfdebugger.streampane.tooltip.ToolTipController;
+import org.apache.pdfbox.util.Charsets;
+
+/**
+ * @author Khyrul Bashar
+ *
+ * A class that shows the COSStream.
+ */
+public class StreamPane implements ActionListener
+{
+    public static final String BEGIN_TEXT_OBJECT = "BT";
+    public static final String END_TEXT_OBJECT = "ET";
+    public static final String SAVE_GRAPHICS_STATE = "q";
+    public static final String RESTORE_GRAPHICS_STATE = "Q";
+    public static final String INLINE_IMAGE_BEGIN = "BI";
+    public static final String IMAGE_DATA = "ID";
+    public static final String INLINE_IMAGE_END = "EI";
+    public static final String BEGIN_MARKED_CONTENT1 = "BMC";
+    public static final String BEGIN_MARKED_CONTENT2 = "BDC";
+    public static final String END_MARKED_CONTENT = "EMC";
+
+    private static final StyleContext CONTEXT = StyleContext.getDefaultStyleContext();
+    private static final Style OPERATOR_STYLE = CONTEXT.addStyle("operator", null);
+    private static final Style NUMBER_STYLE = CONTEXT.addStyle("number", null);
+    private static final Style STRING_STYLE = CONTEXT.addStyle("string", null);
+    private static final Style ESCAPE_STYLE = CONTEXT.addStyle("escape", null);
+    private static final Style NAME_STYLE = CONTEXT.addStyle("name", null);
+    private static final Style INLINE_IMAGE_STYLE = CONTEXT.addStyle("inline_image", null);
+
+    static
+    {
+        StyleConstants.setForeground(OPERATOR_STYLE, new Color(25, 55, 156));
+        StyleConstants.setForeground(NUMBER_STYLE, new Color(51, 86, 18));
+        StyleConstants.setForeground(STRING_STYLE, new Color(128, 35, 32));
+        StyleConstants.setForeground(ESCAPE_STYLE, new Color(179, 49, 36));
+        StyleConstants.setForeground(NAME_STYLE, new Color(140, 38, 145));
+        StyleConstants.setForeground(INLINE_IMAGE_STYLE, new Color(116, 113, 39));
+    }
+
+    private final JPanel panel;
+    private final HexView hexView;
+    private final JTabbedPane tabbedPane;
+    private final StreamPaneView view;
+    private final Stream stream;
+    private ToolTipController tTController;
+    private PDResources resources;
+    private final boolean isContentStream;
+
+    /**
+     * Constructor.
+     *
+     * @param cosStream COSStream instance.
+     * @param isContentStream boolean instance. This says if a stream is content stream or not.
+     * @param isThumb This says if a stream is an thumbnail image or not.
+     * @param resourcesDic COSDictionary instance that holds the resource dictionary for the stream.
+     * @throws IOException if there is an I/O error during internal data transfer.
+     */
+    public StreamPane(COSStream cosStream, boolean isContentStream, boolean isThumb,
+                      COSDictionary resourcesDic) throws IOException
+    {
+        this.isContentStream = isContentStream;
+
+        this.stream = new Stream(cosStream, isThumb);
+        if (resourcesDic != null)
+        {
+            resources = new PDResources(resourcesDic);
+            tTController = new ToolTipController(resources);
+        }
+
+        panel = new JPanel();
+        panel.setPreferredSize(new Dimension(300, 500));
+        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
+
+        view = new StreamPaneView();
+        hexView = new HexView();
+
+        if (stream.isImage())
+        {
+            panel.add(createHeaderPanel(stream.getFilterList(), Stream.IMAGE, this));
+            requestImageShowing();
+        }
+        else
+        {
+            panel.add(createHeaderPanel(stream.getFilterList(), Stream.UNFILTERED, this));
+            requestStreamText(Stream.UNFILTERED);
+        }
+
+        tabbedPane = new JTabbedPane();
+        tabbedPane.add("Text view", view.getStreamPanel());
+        tabbedPane.add("Hex view", hexView.getPane());
+
+        panel.add(tabbedPane);
+    }
+
+    public JComponent getPanel()
+    {
+        return panel;
+    }
+
+    private JPanel createHeaderPanel(List<String> availableFilters, String i, ActionListener actionListener)
+    {
+        JComboBox filters = new JComboBox(availableFilters.toArray());
+        filters.setSelectedItem(i);
+        filters.addActionListener(actionListener);
+
+        JPanel headerPanel = new JPanel(new FlowLayout());
+        headerPanel.add(filters);
+
+        return headerPanel;
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent actionEvent)
+    {
+        if (actionEvent.getActionCommand().equals("comboBoxChanged"))
+        {
+            JComboBox comboBox = (JComboBox) actionEvent.getSource();
+            String currentFilter = (String) comboBox.getSelectedItem();
+
+            try
+            {
+                if (currentFilter.equals(Stream.IMAGE))
+                {
+                    requestImageShowing();
+                    return;
+                }
+                requestStreamText(currentFilter);
+            }
+            catch (IOException e)
+            {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    private void requestImageShowing() throws IOException
+    {
+        if (stream.isImage())
+        {
+            BufferedImage image;
+            synchronized (stream)
+            {
+                image = stream.getImage(resources);
+            }
+            if (image == null)
+            {
+                JOptionPane.showMessageDialog(panel, "image not available (filter missing?)");
+                return;
+            }
+            view.showStreamImage(image);
+
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            ImageIO.write(image, "jpg", baos);
+            baos.flush();
+            byte[] bytes = baos.toByteArray();
+            baos.close();
+            hexView.changeData(bytes);
+        }
+    }
+
+    private void requestStreamText(String command) throws IOException
+    {
+        new DocumentCreator(command).execute();
+        synchronized (stream)
+        {
+            InputStream is = stream.getStream(command);
+            if (is == null)
+            {
+                JOptionPane.showMessageDialog(panel, command + " text not available (filter missing?)");
+                return;
+            }
+            hexView.changeData(IOUtils.toByteArray(is));
+        }
+    }
+
+    /**
+     * A SwingWorker extended class that convert the stream to text loads in a document.
+     */
+    private final class DocumentCreator extends SwingWorker<StyledDocument, Integer>
+    {
+        private final String filterKey;
+        private int indent;
+        private boolean needIndent;
+
+        private DocumentCreator(String filterKey)
+        {
+            this.filterKey = filterKey;
+        }
+
+        @Override
+        protected StyledDocument doInBackground()
+        {
+            synchronized (stream)
+            {
+                InputStream inputStream = stream.getStream(filterKey);
+                if (isContentStream && Stream.UNFILTERED.equals(filterKey))
+                {
+                    StyledDocument document = getContentStreamDocument(inputStream);
+                    if (document != null)
+                    {
+                        return document;
+                    }
+                    return getDocument(stream.getStream(filterKey));
+                }
+                return getDocument(inputStream);
+            }
+        }
+
+        @Override
+        protected void done()
+        {
+            try
+            {
+                view.showStreamText(get(), tTController);
+            }
+            catch (InterruptedException e)
+            {
+                e.printStackTrace();
+            }
+            catch (ExecutionException e)
+            {
+                e.printStackTrace();
+            }
+        }
+
+        private String getStringOfStream(InputStream ioStream)
+        {
+            ByteArrayOutputStream byteArray = new ByteArrayOutputStream();
+            byte[] buffer = new byte[1024];
+            int amountRead;
+            try
+            {
+                while ((amountRead = ioStream.read(buffer, 0, buffer.length)) != -1)
+                {
+                    byteArray.write(buffer, 0, amountRead);
+                }
+            }
+            catch (IOException e)
+            {
+                e.printStackTrace();
+            }
+            try
+            {
+                return byteArray.toString("ISO-8859-1");
+            }
+            catch (UnsupportedEncodingException e)
+            {
+                e.printStackTrace();
+                return null;
+            }
+        }
+
+        private StyledDocument getDocument(InputStream inputStream)
+        {
+            StyledDocument docu = new DefaultStyledDocument();
+            if (inputStream != null)
+            {
+                String data = getStringOfStream(inputStream);
+                try
+                {
+                    docu.insertString(0, data, null);
+                }
+                catch (BadLocationException e)
+                {
+                    e.printStackTrace();
+                }
+            }
+            return docu;
+        }
+
+        private StyledDocument getContentStreamDocument(InputStream inputStream)
+        {
+            StyledDocument docu = new DefaultStyledDocument();
+
+            PDFStreamParser parser;
+            try
+            {
+                parser = new PDFStreamParser(IOUtils.toByteArray(inputStream));
+                parser.parse();
+            }
+            catch (IOException e)
+            {
+                return null;
+            }
+
+            for (Object obj : parser.getTokens())
+            {
+                writeToken(obj, docu);
+            }
+            return docu;
+        }
+
+        private void writeToken(Object obj, StyledDocument docu)
+        {
+            try
+            {
+                if (obj instanceof Operator)
+                {
+                    addOperators(obj, docu);
+                }
+                else
+                {
+                    writeOperand(obj, docu);
+                }
+            }
+            catch (BadLocationException e)
+            {
+                e.printStackTrace();
+            }
+        }
+
+        private void writeOperand(Object obj, StyledDocument docu) throws BadLocationException
+        {
+            writeIndent(docu);
+
+            if (obj instanceof COSName)
+            {
+                String str = "/" + ((COSName) obj).getName();
+                docu.insertString(docu.getLength(), str + " ", NAME_STYLE);
+            }
+            else if (obj instanceof COSBoolean)
+            {
+                String str = obj.toString();
+                docu.insertString(docu.getLength(), str + " ", null);
+            }
+            else if (obj instanceof COSArray)
+            {
+                docu.insertString(docu.getLength(), "[ ", null);
+                for (COSBase elem : (COSArray) obj)
+                {
+                    writeOperand(elem, docu);
+                }
+                docu.insertString(docu.getLength(), "] ", null);
+            }
+            else if (obj instanceof COSString)
+            {
+                docu.insertString(docu.getLength(), "(", null);
+                byte[] bytes = ((COSString) obj).getBytes();
+                for (byte b : bytes)
+                {
+                    int chr = b & 0xff;
+                    if (chr < 0x20 || chr > 0x7e)
+                    {
+                        // non-printable ASCII is shown as an octal escape
+                        String str = String.format("\\%03o", chr);
+                        docu.insertString(docu.getLength(), str, ESCAPE_STYLE);
+                    }
+                    else if (chr == '(' || chr == ')' || chr == '\n' || chr == '\r' ||
+                             chr == '\t' || chr == '\b' || chr == '\f' || chr == '\\')
+                    {
+                        // PDF reserved characters must be escaped
+                        String str = "\\" + (char)chr;
+                        docu.insertString(docu.getLength(), str, ESCAPE_STYLE);
+                    }
+                    else
+                    {
+                        String str = "" + (char)chr;
+                        docu.insertString(docu.getLength(), str, STRING_STYLE);
+                    }
+                }
+                docu.insertString(docu.getLength(), ") ", null);
+            }
+            else if (obj instanceof COSNumber)
+            {
+                String str;
+                if (obj instanceof COSFloat)
+                {
+                    str = Float.toString(((COSFloat) obj).floatValue());
+                }
+                else
+                {
+                    str = Integer.toString(((COSNumber) obj).intValue());
+                }
+                docu.insertString(docu.getLength(), str + " ", NUMBER_STYLE);
+            }
+            else if (obj instanceof COSDictionary)
+            {
+                docu.insertString(docu.getLength(), "<< ", null);
+                COSDictionary dict = (COSDictionary) obj;
+                for (Map.Entry<COSName, COSBase> entry : dict.entrySet())
+                {
+                    writeOperand(entry.getKey(), docu);
+                    writeOperand(entry.getValue(), docu);
+                }
+                docu.insertString(docu.getLength(), ">> ", null);
+            }
+            else
+            {
+                String str = obj.toString();
+                str = str.substring(str.indexOf('{') + 1, str.length() - 1);
+                docu.insertString(docu.getLength(), str + " ", null);
+            }
+        }
+
+        private void addOperators(Object obj, StyledDocument docu) throws BadLocationException
+        {
+            Operator op = (Operator) obj;
+
+            if (op.getName().equals(END_TEXT_OBJECT)
+                    || op.getName().equals(RESTORE_GRAPHICS_STATE)
+                    || op.getName().equals(END_MARKED_CONTENT))
+            {
+                indent--;
+            }
+            writeIndent(docu);
+
+            if (op.getName().equals(INLINE_IMAGE_BEGIN))
+            {
+                docu.insertString(docu.getLength(), INLINE_IMAGE_BEGIN + "\n", OPERATOR_STYLE);
+                COSDictionary dic = op.getImageParameters();
+                for (COSName key : dic.keySet())
+                {
+                    Object value = dic.getDictionaryObject(key);
+                    docu.insertString(docu.getLength(), "/" + key.getName() + " ", null);
+                    writeToken(value, docu);
+                    docu.insertString(docu.getLength(), "\n", null);
+                }
+                String imageString = new String(op.getImageData(), Charsets.ISO_8859_1);
+                docu.insertString(docu.getLength(), IMAGE_DATA + "\n", INLINE_IMAGE_STYLE);
+                docu.insertString(docu.getLength(), imageString, null);
+                docu.insertString(docu.getLength(), "\n", null);
+                docu.insertString(docu.getLength(), INLINE_IMAGE_END + "\n", OPERATOR_STYLE);
+            }
+            else
+            {
+                String operator = ((Operator) obj).getName();
+                docu.insertString(docu.getLength(), operator + "\n", OPERATOR_STYLE);
+
+                // nested opening operators
+                if (op.getName().equals(BEGIN_TEXT_OBJECT) ||
+                    op.getName().equals(SAVE_GRAPHICS_STATE) ||
+                    op.getName().equals(BEGIN_MARKED_CONTENT1) ||
+                    op.getName().equals(BEGIN_MARKED_CONTENT2))
+                {
+                    indent++;
+                }
+            }
+            needIndent = true;
+        }
+
+        void writeIndent(StyledDocument docu) throws BadLocationException
+        {
+            if (needIndent)
+            {
+                for (int i = 0; i < indent; i++)
+                {
+                    docu.insertString(docu.getLength(), "  ", null);
+                }
+                needIndent = false;
+            }
+        }
+    }
+}

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

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/StreamPaneView.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/StreamPaneView.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/StreamPaneView.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/StreamPaneView.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.streampane;
+
+import java.awt.BorderLayout;
+import java.awt.image.BufferedImage;
+import javax.swing.JPanel;
+import javax.swing.text.StyledDocument;
+import org.apache.pdfbox.tools.pdfdebugger.streampane.tooltip.ToolTipController;
+
+/**
+ * @author Khyrul Bashar
+ */
+class StreamPaneView
+{
+    private final JPanel contentPanel;
+
+    /**
+     * Constructor.
+     */
+    StreamPaneView()
+    {
+        contentPanel = new JPanel(new BorderLayout());
+    }
+
+    /**
+     * This shows the stream in text for any of  it's filtered or unfiltered version.
+     * @param document StyledDocument instance that holds the text.
+     * @param toolTipController ToolTipController instance.
+     */
+    void showStreamText(StyledDocument document, ToolTipController toolTipController)
+    {
+        contentPanel.removeAll();
+        StreamTextView textView = new StreamTextView(document, toolTipController);
+        contentPanel.add(textView.getView(), BorderLayout.CENTER);
+        contentPanel.validate();
+    }
+
+
+    /**
+     * This shows the stream as image.
+     * @param image BufferedImage instance that holds the text.
+     */
+    void showStreamImage(BufferedImage image)
+    {
+        contentPanel.removeAll();
+        contentPanel.add(new StreamImageView(image).getView(), BorderLayout.CENTER);
+        contentPanel.validate();
+    }
+
+    public JPanel getStreamPanel()
+    {
+        return contentPanel;
+    }
+}

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

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/StreamTextView.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/StreamTextView.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/StreamTextView.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/StreamTextView.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,129 @@
+/*
+ * 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.streampane;
+
+import java.awt.Font;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseMotionListener;
+import javax.swing.BoxLayout;
+import javax.swing.JComponent;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextPane;
+import javax.swing.SwingUtilities;
+import javax.swing.event.AncestorEvent;
+import javax.swing.event.AncestorListener;
+import javax.swing.text.StyledDocument;
+import org.apache.pdfbox.tools.PDFDebugger;
+import org.apache.pdfbox.tools.pdfdebugger.streampane.tooltip.ToolTipController;
+import org.apache.pdfbox.tools.pdfdebugger.ui.textsearcher.Searcher;
+
+/**
+ * @author Khyrul Bashar
+ * A class that provides the container for the texts when stream is shown in stream pane.
+ */
+class StreamTextView implements MouseMotionListener, AncestorListener
+{
+    private final ToolTipController tTController;
+
+    private JPanel mainPanel;
+    private JTextPane textPane;
+    private Searcher searcher;
+
+    /**
+     * Constructor.
+     * @param document StyledDocument instance which is supposed to be shown in the pane.
+     * @param controller ToolTipController instance.
+     */
+    StreamTextView(StyledDocument document, ToolTipController controller)
+    {
+        tTController = controller;
+        initUI(document);
+    }
+
+    private void initUI(StyledDocument document)
+    {
+        mainPanel = new JPanel();
+
+        textPane = new JTextPane(document);
+        textPane.addMouseMotionListener(this);
+        textPane.setFont(new Font("monospaced", Font.PLAIN, 13));
+        searcher = new Searcher(textPane);
+
+        JScrollPane scrollPane = new JScrollPane(textPane);
+
+        BoxLayout boxLayout = new BoxLayout(mainPanel, BoxLayout.Y_AXIS);
+
+        mainPanel.setLayout(boxLayout);
+
+        mainPanel.add(searcher.getSearchPanel());
+        mainPanel.add(scrollPane);
+
+        searcher.getSearchPanel().setVisible(false);
+
+        mainPanel.addAncestorListener(this);
+
+    }
+
+    JComponent getView()
+    {
+        return mainPanel;
+    }
+
+    @Override
+    public void mouseDragged(MouseEvent mouseEvent)
+    {
+    }
+
+    @Override
+    public void mouseMoved(MouseEvent mouseEvent)
+    {
+        if (tTController != null)
+        {
+            int offset = textPane.viewToModel(mouseEvent.getPoint());
+            textPane.setToolTipText(tTController.getToolTip(offset, textPane));
+        }
+    }
+
+    @Override
+    public void ancestorAdded(AncestorEvent ancestorEvent)
+    {
+        if (ancestorEvent.getAncestor().equals(mainPanel))
+        {
+            PDFDebugger debugger = (PDFDebugger) SwingUtilities.getRoot(mainPanel);
+            debugger.getFindMenu().setEnabled(true);
+            searcher.addMenuListeners(debugger);
+        }
+    }
+
+    @Override
+    public void ancestorRemoved(AncestorEvent ancestorEvent)
+    {
+        if (ancestorEvent.getAncestor().equals(mainPanel))
+        {
+            PDFDebugger debugger = (PDFDebugger) SwingUtilities.getRoot(mainPanel);
+            debugger.getFindMenu().setEnabled(false);
+            searcher.removeMenuListeners(debugger);
+        }
+    }
+
+    @Override
+    public void ancestorMoved(AncestorEvent ancestorEvent)
+    {
+    }
+}

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

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/tooltip/ColorToolTip.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/tooltip/ColorToolTip.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/tooltip/ColorToolTip.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/tooltip/ColorToolTip.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,89 @@
+/*
+ * 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.streampane.tooltip;
+
+import java.awt.Color;
+import java.util.List;
+
+/**
+ * @author Khyrul Bashar
+ * An abstract class for tooltips of color operators.
+ */
+abstract class ColorToolTip implements ToolTip
+{
+    private String toolTipText;
+    /**
+     * provides the Hex value for a Color instance.
+     * @param color
+     * @return
+     */
+    static String colorHexValue(Color color)
+    {
+        return String.format("%02x", color.getRed()) + String.format("%02x", color.getGreen()) +
+                String.format("%02x", color.getBlue());
+    }
+
+    /**
+     * Extract Color values from the row for which tooltip is going to be shown.
+     * @param rowtext String instance,
+     * @return float array containing color values.
+     */
+    float[] extractColorValues(String rowtext)
+    {
+        List<String> words = ToolTipController.getWords(rowtext);
+        words.remove(words.size()-1);
+        float[] values = new float[words.size()];
+        int index = 0;
+        try
+        {
+            for (String word : words)
+            {
+                values[index++] = Float.parseFloat(word);
+            }
+        }
+        catch (NumberFormatException e)
+        {
+            return null;
+        }
+        return values;
+    }
+
+    /**
+     * Create a html string that actually shows a colored rect.
+     * @param hexValue
+     * @return String instance, In html format.
+     */
+    String getMarkUp(String hexValue)
+    {
+         return  "<html>\n" +
+                "<body bgcolor=#ffffff>\n" +
+                "<div style=\"width:50px;height:20px;border:1px; background-color:#"+hexValue+";\"></div></body>\n" +
+                "</html>";
+    }
+
+    public void setToolTipText(String toolTip)
+    {
+        this.toolTipText = toolTip;
+    }
+
+    @Override
+    public String getToolTipText()
+    {
+        return toolTipText;
+    }
+}

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

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/tooltip/FontToolTip.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/tooltip/FontToolTip.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/tooltip/FontToolTip.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/tooltip/FontToolTip.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,77 @@
+/*
+ * 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.streampane.tooltip;
+
+import java.io.IOException;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.pdmodel.PDResources;
+import org.apache.pdfbox.pdmodel.font.PDFont;
+
+/**
+ * @author Khyrul Bashar
+ * A class that provieds tooltip text for font. This shows the name of the font.
+ */
+final class FontToolTip implements ToolTip
+{
+    private String markup;
+
+    /**
+     * Constructor.
+     * @param resources PDResources instance. Which corresponds the resource dictionary containing
+     *                  the concern font.
+     * @param rowText String instance of the tooltip row.
+     */
+    FontToolTip(PDResources resources, String rowText)
+    {
+        initUI(extractFontReference(rowText), resources);
+    }
+
+    private void initUI(String fontReferenceName, PDResources resources)
+    {
+        PDFont font = null;
+        for (COSName name: resources.getFontNames())
+        {
+            if (name.getName().equals(fontReferenceName))
+            {
+                try
+                {
+                    font = resources.getFont(name);
+                }
+                catch (IOException e)
+                {
+                    e.printStackTrace();
+                }
+            }
+        }
+        if (font != null)
+        {
+            markup = "<html>" + font.getName() + "</html>";
+        }
+    }
+
+    private String extractFontReference(String rowText)
+    {
+        return rowText.trim().split(" ")[0].substring(1);
+    }
+
+    @Override
+    public String getToolTipText()
+    {
+        return markup;
+    }
+}

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

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/tooltip/GToolTip.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/tooltip/GToolTip.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/tooltip/GToolTip.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/tooltip/GToolTip.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,46 @@
+/*
+ * 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.streampane.tooltip;
+
+import java.awt.Color;
+
+/**
+ * @author Khyrul Bashar
+ * A class that provide tooltip for G and g.
+ */
+final class GToolTip extends ColorToolTip
+{
+    /**
+     * Constructor.
+     * @param rowText String instance.
+     */
+    GToolTip(String rowText)
+    {
+        createMarkUp(rowText);
+    }
+
+    private void createMarkUp(String rowText)
+    {
+        float[] colorValues = extractColorValues(rowText);
+        if (colorValues != null)
+        {
+            Color color = new Color(colorValues[0], colorValues[0], colorValues[0]);
+            setToolTipText(getMarkUp(colorHexValue(color)));
+        }
+    }
+}

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




Mime
View raw message