/*
* Copyright 2006-2017 ICEsoft Technologies Canada Corp.
*
* 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.icepdf.ri.common.utility.layers;
import org.icepdf.core.pobjects.Document;
import org.icepdf.core.pobjects.OptionalContent;
import org.icepdf.core.pobjects.OptionalContentGroup;
import org.icepdf.core.util.PropertyConstants;
import org.icepdf.ri.common.SwingController;
import org.icepdf.ri.common.views.AbstractDocumentView;
import org.icepdf.ri.common.views.AbstractPageViewComponent;
import org.icepdf.ri.common.views.DocumentViewController;
import org.icepdf.ri.common.views.DocumentViewModel;
import javax.swing.*;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.List;
import java.util.ResourceBundle;
/**
* LayersPanel contains a LayersTree for manipulation of the PDF's optional
* content if present. The panel should only be enabled if the the Document's
* catalog contains a OCProperties entry.
*/
@SuppressWarnings("serial")
public class LayersPanel extends JPanel {
protected DocumentViewController documentViewController;
protected Document currentDocument;
private SwingController controller;
protected LayersTreeNode nodes;
protected DocumentViewModel documentViewModel;
// message bundle for internationalization
ResourceBundle messageBundle;
public LayersPanel(SwingController controller) {
super(true);
setFocusable(true);
this.controller = controller;
this.messageBundle = this.controller.getMessageBundle();
}
private void buildUI() {
JTree tree = new LayersTree(nodes);
tree.setShowsRootHandles(true);
tree.setRootVisible(false);
tree.addMouseListener(new NodeSelectionListener(tree));
this.setLayout(new BorderLayout());
JScrollPane scrollPane = new JScrollPane(tree,
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scrollPane.getVerticalScrollBar().setUnitIncrement(20);
scrollPane.getHorizontalScrollBar().setUnitIncrement(20);
this.add(scrollPane,
BorderLayout.CENTER);
}
public void setDocument(Document document) {
this.currentDocument = document;
documentViewController = controller.getDocumentViewController();
documentViewModel = documentViewController.getDocumentViewModel();
if (this.currentDocument != null) {
OptionalContent optionalContent = currentDocument.getCatalog().getOptionalContent();
List<Object> layersOrder = optionalContent.getOrder();
if (layersOrder != null) {
// check for radio buttons
boolean hasRadioButtons = optionalContent.getRbGroups() != null
&& optionalContent.getRbGroups().size() > 0;
nodes = new LayersTreeNode("Layers");
nodes.setAllowsChildren(true);
buildTree(layersOrder, nodes, hasRadioButtons);
buildUI();
}
} else {
// tear down the old container.
this.removeAll();
}
}
@SuppressWarnings("unchecked")
public void buildTree(List<Object> layersOrder, LayersTreeNode parent, boolean radioGroup) {
LayersTreeNode tmp = null;
boolean selected = true;
// tod recursive build with parent checking.
for (Object obj : layersOrder) {
if (obj instanceof List) {
LayersTreeNode newParent;
if (parent.getChildCount() > 0) {
newParent = (LayersTreeNode) parent.getLastChild();
} else {
newParent = parent;
}
buildTree((List<Object>) obj, newParent, radioGroup);
} else if (obj instanceof String) {
// sets the node as selected if children are all selected.
if (tmp != null && selected) {
tmp.setSelected(true);
}
tmp = new LayersTreeNode(obj);
tmp.setAllowsChildren(true);
nodes.add(tmp);
selected = true;
} else if (obj instanceof OptionalContentGroup) {
LayersTreeNode node = new LayersTreeNode(obj);
node.setAllowsChildren(true);
if (radioGroup) {
node.setSelectionMode(LayersTreeNode.RADIO_SELECTION);
}
parent.add(node);
// check for an unselected state, goal is to select the parent
// if all children are selected.
if (!node.isSelected()) {
selected = false;
}
}
}
}
public void dispose() {
this.removeAll();
}
class NodeSelectionListener extends MouseAdapter {
JTree tree;
NodeSelectionListener(JTree tree) {
this.tree = tree;
}
public void mouseClicked(MouseEvent e) {
int x = e.getX();
int y = e.getY();
int row = tree.getRowForLocation(x, y);
TreePath path = tree.getPathForRow(row);
if (path != null) {
LayersTreeNode node = (LayersTreeNode) path.getLastPathComponent();
boolean isSelected = !(node.isSelected());
node.setSelected(isSelected);
// the current page and repaint
List<AbstractPageViewComponent> pages = documentViewModel.getPageComponents();
AbstractPageViewComponent page = pages.get(documentViewModel.getViewCurrentPageIndex());
// resort page text as layer visibility will have changed.
try {
page.getPage().getText().sortAndFormatText();
} catch (InterruptedException e1) {
// silent running for now.
}
// fire change event.
((AbstractDocumentView)documentViewController.getDocumentView()).firePropertyChange(
PropertyConstants.DOCUMENT_VIEW_REFRESH_CHANGE, false, true);
// repaint the page.
page.repaint();
// repaint the tree so the checkbox states are show correctly.
tree.repaint();
((DefaultTreeModel) tree.getModel()).nodeChanged(node);
if (row == 0) {
tree.revalidate();
tree.repaint();
}
}
}
}
}