| /* |
| * 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.pivot.wtk.skin.terra; |
| |
| import java.io.File; |
| import java.io.IOException; |
| |
| import org.apache.pivot.beans.BXML; |
| import org.apache.pivot.beans.BXMLSerializer; |
| import org.apache.pivot.collections.ArrayList; |
| import org.apache.pivot.collections.Sequence; |
| import org.apache.pivot.serialization.SerializationException; |
| import org.apache.pivot.util.Filter; |
| import org.apache.pivot.util.Vote; |
| import org.apache.pivot.wtk.BoxPane; |
| import org.apache.pivot.wtk.Button; |
| import org.apache.pivot.wtk.ButtonPressListener; |
| import org.apache.pivot.wtk.Component; |
| import org.apache.pivot.wtk.ComponentMouseButtonListener; |
| import org.apache.pivot.wtk.Container; |
| import org.apache.pivot.wtk.FileBrowser; |
| import org.apache.pivot.wtk.FileBrowserListener; |
| import org.apache.pivot.wtk.FileBrowserSheet; |
| import org.apache.pivot.wtk.FileBrowserSheetListener; |
| import org.apache.pivot.wtk.Form; |
| import org.apache.pivot.wtk.Mouse; |
| import org.apache.pivot.wtk.PushButton; |
| import org.apache.pivot.wtk.Sheet; |
| import org.apache.pivot.wtk.Style; |
| import org.apache.pivot.wtk.TablePane; |
| import org.apache.pivot.wtk.TextInput; |
| import org.apache.pivot.wtk.TextInputContentListener; |
| import org.apache.pivot.wtk.Window; |
| |
| /** |
| * Terra file browser sheet skin. |
| */ |
| public class TerraFileBrowserSheetSkin extends TerraSheetSkin implements FileBrowserSheetListener { |
| |
| private static class SaveToFileFilter implements Filter<File> { |
| public final Filter<File> sourceFilter; |
| |
| public SaveToFileFilter(Filter<File> sourceFilter) { |
| this.sourceFilter = sourceFilter; |
| } |
| |
| @Override |
| public boolean include(File file) { |
| return (!file.isDirectory() || (sourceFilter != null && sourceFilter.include(file))); |
| } |
| } |
| |
| @BXML private TablePane tablePane = null; |
| @BXML private BoxPane saveAsBoxPane = null; |
| @BXML private TextInput saveAsTextInput = null; |
| @BXML private FileBrowser fileBrowser = null; |
| @BXML private PushButton okButton = null; |
| @BXML private PushButton cancelButton = null; |
| |
| private boolean updatingSelection = false; |
| private int selectedDirectoryCount = 0; |
| |
| public TerraFileBrowserSheetSkin() { |
| setResizable(true); |
| } |
| |
| @Override |
| public void install(Component component) { |
| super.install(component); |
| |
| final FileBrowserSheet fileBrowserSheet = (FileBrowserSheet) component; |
| fileBrowserSheet.setMinimumWidth(360); |
| fileBrowserSheet.setMinimumHeight(180); |
| |
| // Load the sheet content |
| BXMLSerializer bxmlSerializer = new BXMLSerializer(); |
| |
| Component content; |
| try { |
| content = (Component) bxmlSerializer.readObject(TerraFileBrowserSheetSkin.class, |
| "terra_file_browser_sheet_skin.bxml", true); |
| } catch (IOException exception) { |
| throw new RuntimeException(exception); |
| } catch (SerializationException exception) { |
| throw new RuntimeException(exception); |
| } |
| |
| fileBrowserSheet.setContent(content); |
| |
| bxmlSerializer.bind(this, TerraFileBrowserSheetSkin.class); |
| |
| // set the same rootDirectory to fileBrowser |
| fileBrowser.setRootDirectory(fileBrowserSheet.getRootDirectory()); |
| |
| saveAsTextInput.getTextInputContentListeners().add(new TextInputContentListener() { |
| @Override |
| public void textChanged(TextInput textInput) { |
| Form.clearFlag(saveAsBoxPane); |
| updateOKButtonState(); |
| } |
| }); |
| |
| fileBrowser.getFileBrowserListeners().add(new FileBrowserListener() { |
| @Override |
| public void rootDirectoryChanged(FileBrowser fileBrowserArgument, |
| File previousRootDirectory) { |
| updatingSelection = true; |
| |
| fileBrowserSheet.setRootDirectory(fileBrowserArgument.getRootDirectory()); |
| |
| updatingSelection = false; |
| |
| selectedDirectoryCount = 0; |
| updateOKButtonState(); |
| } |
| |
| @Override |
| public void selectedFileAdded(FileBrowser fileBrowserArgument, File file) { |
| if (file.isDirectory()) { |
| selectedDirectoryCount++; |
| } |
| |
| updateOKButtonState(); |
| } |
| |
| @Override |
| public void selectedFileRemoved(FileBrowser fileBrowserArgument, File file) { |
| if (file.isDirectory()) { |
| selectedDirectoryCount--; |
| } |
| |
| updateOKButtonState(); |
| } |
| |
| @Override |
| public void selectedFilesChanged(FileBrowser fileBrowserArgument, |
| Sequence<File> previousSelectedFiles) { |
| selectedDirectoryCount = 0; |
| |
| Sequence<File> selectedFiles = fileBrowserArgument.getSelectedFiles(); |
| for (int i = 0, n = selectedFiles.getLength(); i < n; i++) { |
| File selectedFile = selectedFiles.get(i); |
| |
| if (selectedFile.isDirectory()) { |
| selectedDirectoryCount++; |
| } |
| } |
| |
| if (!fileBrowserArgument.isMultiSelect()) { |
| File selectedFile = fileBrowserArgument.getSelectedFile(); |
| |
| if (selectedFile != null && !selectedFile.isDirectory()) { |
| saveAsTextInput.setText(selectedFile.getName()); |
| } |
| } |
| |
| updateOKButtonState(); |
| } |
| }); |
| |
| fileBrowser.getComponentMouseButtonListeners().add( |
| new ComponentMouseButtonListener() { |
| private File file = null; |
| |
| @Override |
| public boolean mouseClick(Component componentArgument, Mouse.Button button, int x, |
| int y, int count) { |
| boolean consumed = false; |
| |
| FileBrowserSheet.Mode mode = fileBrowserSheet.getMode(); |
| |
| if (count == 1) { |
| file = fileBrowser.getFileAt(x, y); |
| } else if (count == 2) { |
| File fileLocal = fileBrowser.getFileAt(x, y); |
| |
| if (fileLocal != null && this.file != null && fileLocal.equals(this.file) |
| && fileBrowser.isFileSelected(fileLocal)) { |
| if (mode == FileBrowserSheet.Mode.OPEN |
| || mode == FileBrowserSheet.Mode.OPEN_MULTIPLE) { |
| if (!fileLocal.isDirectory()) { |
| fileBrowserSheet.close(true); |
| consumed = true; |
| } |
| } |
| } |
| } |
| |
| return consumed; |
| } |
| }); |
| |
| okButton.getButtonPressListeners().add(new ButtonPressListener() { |
| @Override |
| public void buttonPressed(Button button) { |
| fileBrowserSheet.close(true); |
| } |
| }); |
| |
| cancelButton.getButtonPressListeners().add(new ButtonPressListener() { |
| @Override |
| public void buttonPressed(Button button) { |
| fileBrowserSheet.close(false); |
| } |
| }); |
| |
| // Add this as a file browser sheet listener |
| fileBrowserSheet.getFileBrowserSheetListeners().add(this); |
| |
| modeChanged(fileBrowserSheet, null); |
| rootDirectoryChanged(fileBrowserSheet, null); |
| selectedFilesChanged(fileBrowserSheet, null); |
| } |
| |
| public boolean isHideDisabledFiles() { |
| return fileBrowser.getStyles().getBoolean(Style.hideDisabledFiles); |
| } |
| |
| public void setHideDisabledFiles(boolean hideDisabledFiles) { |
| fileBrowser.getStyles().put(Style.hideDisabledFiles, hideDisabledFiles); |
| } |
| |
| public boolean isShowHiddenFiles() { |
| return fileBrowser.getStyles().getBoolean(Style.showHiddenFiles); |
| } |
| |
| public void setShowHiddenFiles(boolean showHiddenFiles) { |
| fileBrowser.getStyles().put(Style.showHiddenFiles, showHiddenFiles); |
| } |
| |
| public boolean getShowOKButtonFirst() { |
| Container parent = okButton.getParent(); |
| return parent.indexOf(okButton) < parent.indexOf(cancelButton); |
| } |
| |
| public void setShowOKButtonFirst(boolean showOKButtonFirst) { |
| if (showOKButtonFirst != getShowOKButtonFirst()) { |
| Container parent = okButton.getParent(); |
| parent.remove(okButton); |
| parent.remove(cancelButton); |
| |
| if (showOKButtonFirst) { |
| parent.add(okButton); |
| parent.add(cancelButton); |
| } else { |
| parent.add(cancelButton); |
| parent.add(okButton); |
| } |
| } |
| } |
| |
| @Override |
| public void windowOpened(Window window) { |
| super.windowOpened(window); |
| window.requestFocus(); |
| } |
| |
| @Override |
| public Vote previewSheetClose(final Sheet sheet, final boolean result) { |
| Vote vote = null; |
| |
| if (result && !okButton.isEnabled()) { |
| vote = Vote.DENY; |
| } else { |
| if (result) { |
| updatingSelection = true; |
| |
| FileBrowserSheet fileBrowserSheet = (FileBrowserSheet) sheet; |
| FileBrowserSheet.Mode mode = fileBrowserSheet.getMode(); |
| |
| switch (mode) { |
| case OPEN: |
| case OPEN_MULTIPLE: |
| case SAVE_TO: |
| fileBrowserSheet.setSelectedFiles(fileBrowser.getSelectedFiles()); |
| break; |
| |
| case SAVE_AS: |
| String fileName = saveAsTextInput.getText(); |
| // Contents of the entry field could be: |
| // 1. Just a new file name in the current root directory |
| // 2. A relative or absolute path that is an existing directory |
| // to navigate to |
| // 3. A relative or absolute path including the new file name |
| // in an existing directory |
| // So, first make it an absolute path |
| File selectedFile = new File(fileName); |
| if (!selectedFile.isAbsolute() && !fileName.startsWith(File.separator)) { |
| selectedFile = new File(fileBrowser.getRootDirectory(), fileName); |
| } else { |
| selectedFile = selectedFile.getAbsoluteFile(); |
| } |
| if (selectedFile.exists() && selectedFile.isDirectory()) { |
| try { |
| File root = selectedFile.getCanonicalFile(); |
| fileBrowserSheet.setRootDirectory(root); |
| fileBrowser.setRootDirectory(root); |
| saveAsTextInput.setText(""); |
| } catch (IOException ioe) { |
| Form.setFlag(saveAsBoxPane, new Form.Flag()); |
| } |
| selectedFile = null; |
| vote = Vote.DENY; |
| } else { |
| File root = selectedFile.getParentFile(); |
| if (root != null && root.exists() && root.isDirectory()) { |
| try { |
| fileBrowserSheet.setRootDirectory(root.getCanonicalFile()); |
| selectedFile = new File(selectedFile.getName()); |
| } catch (IOException ioe) { |
| Form.setFlag(saveAsBoxPane, new Form.Flag()); |
| selectedFile = null; |
| vote = Vote.DENY; |
| } |
| } else { |
| // Could be an error message here |
| // ("Directory does not exist") |
| Form.setFlag(saveAsBoxPane, new Form.Flag()); |
| selectedFile = null; |
| vote = Vote.DENY; |
| } |
| } |
| if (selectedFile != null) { |
| fileBrowserSheet.setSelectedFiles(new ArrayList<>(selectedFile)); |
| } |
| break; |
| |
| default: |
| break; |
| } |
| |
| updatingSelection = false; |
| } |
| if (vote == null) { |
| vote = super.previewSheetClose(sheet, result); |
| } |
| } |
| |
| return vote; |
| } |
| |
| @Override |
| public void modeChanged(FileBrowserSheet fileBrowserSheet, FileBrowserSheet.Mode previousMode) { |
| FileBrowserSheet.Mode mode = fileBrowserSheet.getMode(); |
| |
| fileBrowser.getStyles().put(Style.keyboardFolderTraversalEnabled, |
| (mode != FileBrowserSheet.Mode.SAVE_TO)); |
| |
| switch (mode) { |
| case OPEN: |
| saveAsBoxPane.setVisible(false); |
| fileBrowser.setMultiSelect(false); |
| break; |
| |
| case OPEN_MULTIPLE: |
| saveAsBoxPane.setVisible(false); |
| fileBrowser.setMultiSelect(true); |
| break; |
| |
| case SAVE_AS: |
| saveAsBoxPane.setVisible(true); |
| fileBrowser.setMultiSelect(false); |
| break; |
| |
| case SAVE_TO: |
| saveAsBoxPane.setVisible(false); |
| fileBrowser.setMultiSelect(false); |
| break; |
| |
| default: |
| break; |
| } |
| |
| updateDisabledFileFilter(); |
| updateOKButtonState(); |
| } |
| |
| @Override |
| public void rootDirectoryChanged(FileBrowserSheet fileBrowserSheet, File previousRootDirectory) { |
| if (!updatingSelection) { |
| fileBrowser.setRootDirectory(fileBrowserSheet.getRootDirectory()); |
| } |
| } |
| |
| @Override |
| public void selectedFilesChanged(FileBrowserSheet fileBrowserSheet, |
| Sequence<File> previousSelectedFiles) { |
| if (!updatingSelection) { |
| Sequence<File> selectedFiles = fileBrowserSheet.getSelectedFiles(); |
| fileBrowser.setSelectedFiles(selectedFiles); |
| |
| if (fileBrowser.getSelectedFiles().getLength() == 0 && selectedFiles.getLength() == 1) { |
| // The file does not currently exist; set the file name in the |
| // text input if the parent directory is the same as the root |
| // directory |
| File selectedFile = selectedFiles.get(0); |
| |
| File rootDirectory = fileBrowser.getRootDirectory(); |
| if (rootDirectory.equals(selectedFile.getParentFile())) { |
| saveAsTextInput.setText(selectedFile.getName()); |
| } |
| } |
| } |
| } |
| |
| @Override |
| public void disabledFileFilterChanged(FileBrowserSheet fileBrowserSheet, |
| Filter<File> previousDisabledFileFilter) { |
| updateDisabledFileFilter(); |
| } |
| |
| private void updateDisabledFileFilter() { |
| FileBrowserSheet fileBrowserSheet = (FileBrowserSheet) getComponent(); |
| Filter<File> disabledFileFilter = fileBrowserSheet.getDisabledFileFilter(); |
| |
| FileBrowserSheet.Mode mode = fileBrowserSheet.getMode(); |
| if (mode == FileBrowserSheet.Mode.SAVE_TO) { |
| disabledFileFilter = new SaveToFileFilter(disabledFileFilter); |
| } |
| |
| fileBrowser.setDisabledFileFilter(disabledFileFilter); |
| } |
| |
| private void updateOKButtonState() { |
| FileBrowserSheet fileBrowserSheet = (FileBrowserSheet) getComponent(); |
| |
| FileBrowserSheet.Mode mode = fileBrowserSheet.getMode(); |
| Sequence<File> selectedFiles = fileBrowser.getSelectedFiles(); |
| |
| switch (mode) { |
| case OPEN: |
| case OPEN_MULTIPLE: |
| okButton.setEnabled(selectedFiles.getLength() > 0 && selectedDirectoryCount == 0); |
| break; |
| |
| case SAVE_AS: |
| okButton.setEnabled(saveAsTextInput.getCharacterCount() > 0); |
| break; |
| |
| case SAVE_TO: |
| okButton.setEnabled(selectedDirectoryCount > 0); |
| break; |
| |
| default: |
| break; |
| } |
| } |
| |
| public void addComponent(Component component) { |
| TablePane.Row row = new TablePane.Row(-1); |
| row.add(component); |
| Sequence<TablePane.Row> rows = tablePane.getRows(); |
| rows.insert(row, rows.getLength() - 1); |
| } |
| } |