/**
* This file is part of HIDB2.
*
* HIDB2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* HIDB2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser Public License for more details.
*
* You should have received a copy of the GNU Lesser Public License
* along with HIDB2. If not, see <http://www.gnu.org/licenses/>.
*/
package hidb2.gui;
import hidb2.Activator;
import hidb2.gui.action.AddAsCard;
import hidb2.gui.action.AddAsFolder;
import hidb2.gui.action.OpenFile;
import hidb2.gui.action.OpenIcon;
import hidb2.gui.action.ViewIcon;
import hidb2.gui.editor.FolderListEditor;
import hidb2.gui.node.DefaultNode;
import hidb2.gui.node.FileNode;
import hidb2.gui.preferences.PrefConst;
import hidb2.gui.util.IReStartableView;
import java.io.File;
import java.util.List;
import java.util.logging.Logger;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.ScrollBar;
import org.eclipse.swt.widgets.Tracker;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.DrillDownAdapter;
import org.eclipse.ui.part.ViewPart;
/**
* Dedicated file browser.
*
*/
public class FileBrowseView extends ViewPart implements IReStartableView
{
public static final String ID = "HIDB2.FileBrowseView";
static Logger log = Logger.getLogger("hidb2.gui");
private Composite _parent;
private SashForm _sashForm;
private TreeViewer _viewer;
/** Graphic area where icons are drawn */
private Canvas _drawArea;
private DrillDownAdapter drillDownAdapter;
private OpenFile openAction;
private OpenIcon openIconAction;
private ViewIcon viewIconAction;
private AddAsFolder addAsFolderAction;
private AddAsCard addAsCardAction;
private Action doubleClickAction;
private FileBrowserParam _fbparam;
/** Default font. */
public static Font fntStd;
private CellList _lstCell;
private int virtImgWidth = 512;
private int virtImgHeight = 512;
private int nbColumns = 0;
private int nbLines = 0;
private ScrollBar _vBar;
private ScrollBar _hBar;
private Point _origin = new Point(0, 0);
class NameSorter extends ViewerSorter
{
}
/**
* Method used by the Preference Page to change fonts.
*/
public void restart()
{
IPreferenceStore pref = Activator.getDefault().getPreferenceStore();
_fbparam = new FileBrowserParam(pref);
_viewer.setContentProvider(new FileBrowseViewContentProvider(this, _fbparam));
_viewer.refresh();
}
@Override
public void createPartControl(Composite parent)
{
_parent = parent;
IPreferenceStore pref = Activator.getDefault().getPreferenceStore();
_fbparam = new FileBrowserParam(pref);
parent.setLayout(new FillLayout());
fillPullDownMenu();
_sashForm = new SashForm(_parent, SWT.HORIZONTAL);
createDirTree();
createCanvas();
}
/**
* Create the file tree viewer.
*/
private void createDirTree()
{
_viewer = new TreeViewer(_sashForm, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
drillDownAdapter = new DrillDownAdapter(_viewer);
_viewer.setContentProvider(new FileBrowseViewContentProvider(this, _fbparam));
_viewer.setLabelProvider(new FileBrowseViewLabelProvider());
_viewer.setSorter(new NameSorter());
_viewer.setInput(getViewSite());
makeActions();
hookContextMenu();
hookDoubleClickAction();
contributeToActionBars();
_viewer.addSelectionChangedListener(new ISelectionChangedListener()
{
@Override
public void selectionChanged(SelectionChangedEvent event)
{
ISelection selection = _viewer.getSelection();
if (selection.isEmpty())
{
// Clear drawing area
}
else
{
FileNode fn = (FileNode) ((IStructuredSelection) selection).getFirstElement();
File fic = fn.getFile();
updateCanvas(fic);
_drawArea.redraw();
}
}
});
// Add Custom Drawing callbacks
Tree tr = _viewer.getTree();
tr.addListener(SWT.MeasureItem, new Listener()
{
public void handleEvent(Event event)
{
((DefaultNode) ((TreeItem) event.item).getData()).mesureItem(event);
}
});
tr.addListener(SWT.EraseItem, new Listener()
{
public void handleEvent(Event event)
{
((DefaultNode) ((TreeItem) event.item).getData()).eraseItem(event);
}
});
tr.addListener(SWT.PaintItem, new Listener()
{
public void handleEvent(Event event)
{
((DefaultNode) ((TreeItem) event.item).getData()).paintItem(event);
}
});
//par defaut on ouvre au niveau 1
_viewer.expandToLevel(1);
}
private void hookContextMenu()
{
// File Menu
MenuManager menuMgr = new MenuManager("#PopupMenu", "fr.eposer.navtree.ObjArbo.pm");
menuMgr.setRemoveAllWhenShown(true);
menuMgr.addMenuListener(new IMenuListener()
{
public void menuAboutToShow(IMenuManager manager)
{
fillContextMenu(manager);
}
});
Menu menu = menuMgr.createContextMenu(_viewer.getControl());
_viewer.getControl().setMenu(menu);
getSite().registerContextMenu(menuMgr.getId(), menuMgr, _viewer);
}
private void contributeToActionBars()
{
IActionBars bars = getViewSite().getActionBars();
fillLocalPullDown(bars.getMenuManager());
fillLocalToolBar(bars.getToolBarManager());
}
/* (non-Javadoc)
* @see org.eclipse.ui.part.WorkbenchPart#dispose()
*/
@Override
public void dispose()
{
super.dispose();
// Dispose used Fonts
DefaultNode.dispose();
}
private void fillLocalPullDown(IMenuManager manager)
{
manager.add(openAction);
}
private void fillContextMenu(IMenuManager manager)
{
manager.add(openAction);
manager.add(new Separator());
// Other plug-ins can contribute there actions here
manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
manager.add(new Separator());
drillDownAdapter.addNavigationActions(manager);
}
private void fillLocalToolBar(IToolBarManager manager)
{
manager.add(openAction);
manager.add(new Separator());
drillDownAdapter.addNavigationActions(manager);
}
private void makeActions()
{
openAction = new OpenFile(_viewer);
doubleClickAction = new OpenFile(_viewer);
openIconAction = new OpenIcon(this);
viewIconAction = new ViewIcon(this);
addAsFolderAction = new AddAsFolder(this);
addAsCardAction = new AddAsCard(this);
}
private void hookDoubleClickAction()
{
_viewer.addDoubleClickListener(new IDoubleClickListener()
{
public void doubleClick(DoubleClickEvent event)
{
doubleClickAction.run();
}
});
}
/**
* Create the icon drawing area.
*/
private void createCanvas()
{
IPreferenceStore pref = Activator.getDefault().getPreferenceStore();
String fntStdName = pref.getString(PrefConst.P_FNT_FILEBROWSE_STD);
FontData fntStdData = new FontData(fntStdName);
fntStd = new Font(_sashForm.getDisplay(), fntStdData);
_drawArea = new Canvas(_sashForm, SWT.NO_REDRAW_RESIZE | SWT.V_SCROLL | SWT.H_SCROLL);
_vBar = _drawArea.getVerticalBar();
_hBar = _drawArea.getHorizontalBar();
_hBar.addListener(SWT.Selection, new Listener()
{
public void handleEvent(Event e)
{
int hSelection = _hBar.getSelection();
int destX = -hSelection - _origin.x;
_drawArea.scroll(destX, 0, 0, 0, virtImgWidth, virtImgHeight, false);
_origin.x = -hSelection;
}
});
_vBar.addListener(SWT.Selection, new Listener()
{
public void handleEvent(Event e)
{
int vSelection = _vBar.getSelection();
int destY = -vSelection - _origin.y;
_drawArea.scroll(0, destY, 0, 0, virtImgWidth, virtImgHeight, false);
_origin.y = -vSelection;
}
});
_drawArea.addListener(SWT.Resize, new Listener()
{
public void handleEvent(Event e)
{
if (_lstCell == null)
{
return;
}
computeDASize();
_lstCell.computeCellPos(nbColumns);
_drawArea.redraw();
}
});
_drawArea.addListener(SWT.Paint, new Listener()
{
public void handleEvent(Event e)
{
// No repaint, if list empty (but cleaning could be useful)
if (_lstCell == null)
{
return;
}
e.gc.setFont(fntStd);
Rectangle visibleRect = _drawArea.getClientArea();
visibleRect.x -= _origin.x;
visibleRect.y -= _origin.y;
_lstCell.draw(e.gc, visibleRect, _origin, nbColumns);
}
});
_drawArea.addMouseListener(new MouseListener()
{
Tracker tracker = new Tracker(_drawArea, SWT.RESIZE);
@Override
public void mouseDoubleClick(MouseEvent e)
{
// Change Selection and open the selected object.
_lstCell.clearSelection();
// Retrieve CanvasCell in absolute coordinates
CanvasCell cc = _lstCell.find(e.x - _origin.x, e.y - _origin.y);
if (cc != null)
{
cc.isSelected = true;
_drawArea.redraw();
openIconAction.run();
}
_drawArea.redraw();
}
@Override
public void mouseDown(MouseEvent e)
{
switch (e.button)
{
case 1:
if ((e.stateMask & (SWT.SHIFT | SWT.CTRL)) == 0)
{
_lstCell.clearSelection();
_drawArea.redraw();
}
tracker.setRectangles(new Rectangle[]
{
new Rectangle(e.x, e.y, 16, 16),
});
boolean rb = tracker.open();
if (rb)
{
Rectangle[] tabrect = tracker.getRectangles();
Rectangle rSelect = tabrect[0];
// Retrieve absolute coordinates
rSelect.x -= _origin.x;
rSelect.y -= _origin.y;
if ((e.stateMask & SWT.SHIFT) == SWT.SHIFT)
{
// Select images in the selection area
_lstCell.select(rSelect);
}
else
{
if ((e.stateMask & SWT.CTRL) == SWT.CTRL)
{
// Toggle selection status for images of the selection area
_lstCell.toggle(rSelect);
}
else
{
// Select images in the selection area
_lstCell.select(rSelect);
}
}
_drawArea.redraw();
}
break;
case 2:
break;
case 3: // Display Popup Menu is done automatically
// System.out.println("Btn3");
break;
}
}
@Override
public void mouseUp(MouseEvent e)
{
}
});
// Create a Popup for the drawing area
MenuManager menuMgr = new MenuManager("#PopupMenu", null);
menuMgr.setRemoveAllWhenShown(true);
menuMgr.addMenuListener(new IMenuListener()
{
public void menuAboutToShow(IMenuManager manager)
{
int nbs = _lstCell.getNbSelected();
if (nbs > 0)
{
manager.add(openIconAction);
manager.add(viewIconAction);
IWorkbenchWindow wbwin = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
IWorkbenchPage iwp = wbwin.getActivePage();
IEditorPart iep = iwp.getActiveEditor();
if ((iep != null) && (iep instanceof FolderListEditor))
{
FolderListEditor fle = (FolderListEditor) iep;
addAsFolderAction.setEditor(fle);
manager.add(addAsFolderAction);
addAsCardAction.setEditor(fle);
manager.add(addAsCardAction);
}
}
// manager.add(new Separator());
}
});
Menu menu = menuMgr.createContextMenu(_drawArea);
_drawArea.setMenu(menu);
}
/**
* Compute the size of the drawing area.
*/
private void computeDASize()
{
int nbFiles = _lstCell.size();
Rectangle clientRect = _drawArea.getClientArea();
// System.out.println("Init DA Size :" + clientRect);
nbColumns = Math.max(clientRect.width / _fbparam.cellWidth, 1);
nbLines = (nbFiles + nbColumns - 1) / nbColumns;
virtImgWidth = Math.max(nbColumns * _fbparam.cellWidth, clientRect.width);
virtImgHeight = Math.max(nbLines * _fbparam.cellHeight, clientRect.height);
// _drawArea.setSize(virtImgWidth, virtImgHeight);
_hBar.setMaximum(virtImgWidth - clientRect.width);
_hBar.setSelection(0);
_hBar.setPageIncrement(_fbparam.cellWidth / 2);
_vBar.setMaximum(virtImgHeight - clientRect.height);
_vBar.setSelection(0);
_vBar.setPageIncrement(_fbparam.cellHeight / 2);
_origin.x = 0;
_origin.y = 0;
// System.out.println("New DA Size :" + virtImgWidth + "x" + virtImgHeight + " " + nbColumns + "x" + nbLines);
}
private void updateCanvas(File fdir)
{
File[] tabFic = fdir.listFiles();
// Dispose previously allocated images of CanvasCells
if (_lstCell == null)
{
_lstCell = new CellList(tabFic, _fbparam);
}
else
{
_lstCell.set(tabFic, _fbparam);
}
computeDASize();
// Prepare (load) Icons
for (CanvasCell cc : _lstCell)
{
cc.computeIcon(_drawArea.getDisplay());
}
_lstCell.computeCellPos(nbColumns);
}
public TreeViewer getTree()
{
return _viewer;
}
@Override
public void setFocus()
{
}
private void fillPullDownMenu()
{
// Fill Pulldown menu
IActionBars bars = getViewSite().getActionBars();
IMenuManager manager = bars.getMenuManager();
manager.add(new SwitchListIconAction());
}
/**
*
* @return
*/
public List<File> getSelection()
{
return _lstCell.getSelection();
}
class SwitchListIconAction extends Action
{
public SwitchListIconAction()
{
super("Icon/List", IAction.AS_CHECK_BOX);
setChecked(true);
}
public void run()
{
if (isChecked())
{
// TODO : Manage List/Icon switch
_fbparam.view = FileBrowserParam.VIEWTYPE.DETAILED_LIST;
}
else
{
_fbparam.view = FileBrowserParam.VIEWTYPE.ICON;
}
}
}
class ShowRootsAction extends Action
{
public ShowRootsAction()
{
super("Show Roots", IAction.AS_CHECK_BOX);
setChecked(true);
}
public void run()
{
if (isChecked())
{
// TODO : Manage Roots switch
_fbparam.viewRoots = true;
}
else
{
_fbparam.view = FileBrowserParam.VIEWTYPE.ICON;
}
}
}
}