public Component getPreview(WebLookAndFeelDemo owner) {
    // Simple decorated file breadcrumb (by default file system root is used)
    WebFileBreadcrumb dfb = new WebFileBreadcrumb(FileUtils.getDiskRoots()[0]);

    // Simple decorated file breadcrumb (by default file system root is used)
    WebFileBreadcrumb sfb = new WebFileBreadcrumb();

    // Simple undecorated file breadcrumb (user home used as root
    WebFileBreadcrumb hfb = new WebFileBreadcrumb(FileUtils.getUserHomePath(), false);
    hfb.setEncloseLastElement(true);

    return new GroupPanel(4, false, new GroupPanel(dfb), new GroupPanel(sfb), new GroupPanel(hfb));
  }
/**
 * This custom component provides a directory chooser functionality. It similar to file chooser
 * component but has its own unique interface and doesn't need a lot of configuring to use.
 *
 * @author Mikle Garin
 */
public class WebDirectoryChooserPanel extends WebPanel {
  /** Used icons. */
  protected static final ImageIcon FOLDER_UP_ICON =
      new ImageIcon(WebDirectoryChooserPanel.class.getResource("icons/folder_up.png"));

  protected static final ImageIcon FOLDER_HOME_ICON =
      new ImageIcon(WebDirectoryChooserPanel.class.getResource("icons/folder_home.png"));
  protected static final ImageIcon FOLDER_NEW_ICON =
      new ImageIcon(WebDirectoryChooserPanel.class.getResource("icons/folder_new.png"));
  protected static final ImageIcon REFRESH_ICON =
      new ImageIcon(WebDirectoryChooserPanel.class.getResource("icons/refresh.png"));
  protected static final ImageIcon REMOVE_ICON =
      new ImageIcon(WebDirectoryChooserPanel.class.getResource("icons/remove.png"));

  /** Directory chooser listeners. */
  protected List<DirectoryChooserListener> listeners = new ArrayList<DirectoryChooserListener>(1);

  /** Currently selected directory. */
  protected File selectedDirectory = FileUtils.getDiskRoots()[0];

  /** File filter. */
  protected AbstractFileFilter filter = GlobalConstants.NON_HIDDEN_DIRECTORIES_FILTER;

  /** Toolbar components. */
  protected WebButton folderUp;

  protected WebButton folderHome;
  protected WebButton folderNew;
  protected WebButton refresh;
  protected WebButton remove;

  /** Path field. */
  protected WebPathField webPathField;

  /** File tree. */
  protected WebFileTree fileTree;

  protected TreeSelectionListener fileTreeListener;

  /** Constructs new directory chooser panel. */
  public WebDirectoryChooserPanel() {
    super();

    // Panel settings
    setOpaque(true);

    // Controls pane
    final WebToolBar contolsToolbar = new WebToolBar(WebToolBar.HORIZONTAL);
    contolsToolbar.setToolbarStyle(ToolbarStyle.attached);
    contolsToolbar.setFloatable(false);

    folderUp = new WebButton(FOLDER_UP_ICON);
    folderUp.setLanguage("weblaf.ex.dirchooser.folderup");
    folderUp
        .addHotkey(WebDirectoryChooserPanel.this, Hotkey.ALT_UP)
        .setHotkeyDisplayWay(TooltipWay.down);
    folderUp.setRolloverDecoratedOnly(true);
    folderUp.addActionListener(
        new ActionListener() {
          @Override
          public void actionPerformed(final ActionEvent e) {
            if (selectedDirectory != null) {
              updateSelectedDirectory(selectedDirectory.getParentFile(), true, true);
            }
          }
        });
    contolsToolbar.add(folderUp);

    folderHome = new WebButton(FOLDER_HOME_ICON);
    folderHome.setLanguage("weblaf.ex.dirchooser.home");
    folderHome
        .addHotkey(WebDirectoryChooserPanel.this, Hotkey.ALT_H)
        .setHotkeyDisplayWay(TooltipWay.trailing);
    folderHome.setRolloverDecoratedOnly(true);
    folderHome.addActionListener(
        new ActionListener() {
          @Override
          public void actionPerformed(final ActionEvent e) {
            updateSelectedDirectory(FileUtils.getUserHome(), true, true);
          }
        });
    contolsToolbar.add(folderHome);

    contolsToolbar.addSeparator();

    for (final File file : FileTreeRootType.drives.getRoots()) {
      final WebButton root = new WebButton(FileUtils.getFileIcon(file));
      TooltipManager.setTooltip(root, FileUtils.getDisplayFileName(file));
      root.setRolloverDecoratedOnly(true);
      root.addActionListener(
          new ActionListener() {
            @Override
            public void actionPerformed(final ActionEvent e) {
              updateSelectedDirectory(file, true, true);
            }
          });
      contolsToolbar.add(root);
    }

    refresh = new WebButton(REFRESH_ICON);
    refresh.setLanguage("weblaf.ex.dirchooser.refresh");
    refresh
        .addHotkey(WebDirectoryChooserPanel.this, Hotkey.F5)
        .setHotkeyDisplayWay(TooltipWay.leading);
    refresh.setRolloverDecoratedOnly(true);
    refresh.addActionListener(
        new ActionListener() {
          @Override
          public void actionPerformed(final ActionEvent e) {
            if (selectedDirectory != null) {
              fileTree.reloadChilds(selectedDirectory);
            } else {
              fileTree.reloadRootNode();
            }
          }
        });
    contolsToolbar.add(refresh, ToolbarLayout.END);

    folderNew = new WebButton(FOLDER_NEW_ICON);
    folderNew.setLanguage("weblaf.ex.dirchooser.newfolder");
    folderNew
        .addHotkey(WebDirectoryChooserPanel.this, Hotkey.CTRL_N)
        .setHotkeyDisplayWay(TooltipWay.down);
    folderNew.setRolloverDecoratedOnly(true);
    folderNew.addActionListener(
        new ActionListener() {
          @Override
          public void actionPerformed(final ActionEvent e) {
            if (selectedDirectory != null) {
              final String defaultName = LanguageManager.get("weblaf.ex.dirchooser.newfolder.name");
              final String freeName = FileUtils.getAvailableName(selectedDirectory, defaultName);
              final File file = new File(selectedDirectory, freeName);
              if (file.mkdir()) {
                // Updating filestree
                fileTree.addFile(selectedDirectory, file);

                // Editing added folder name
                fileTree.startEditingFile(file);
              } else {
                final String message =
                    LanguageManager.get("weblaf.ex.dirchooser.newfolder.error.text");
                final String title =
                    LanguageManager.get("weblaf.ex.dirchooser.newfolder.error.title");
                WebOptionPane.showMessageDialog(
                    WebDirectoryChooserPanel.this, message, title, WebOptionPane.ERROR_MESSAGE);
              }
            }
          }
        });
    contolsToolbar.add(folderNew, ToolbarLayout.END);

    remove = new WebButton(REMOVE_ICON);
    remove.setLanguage("weblaf.ex.dirchooser.delete");
    remove
        .addHotkey(WebDirectoryChooserPanel.this, Hotkey.DELETE)
        .setHotkeyDisplayWay(TooltipWay.down);
    remove.setRolloverDecoratedOnly(true);
    remove.addActionListener(
        new ActionListener() {
          @Override
          public void actionPerformed(final ActionEvent e) {
            final File file = fileTree.getSelectedFile();
            if (file == null) {
              return;
            }

            // Displaying delete confirmation
            final String message = LanguageManager.get("weblaf.ex.dirchooser.delete.confirm.text");
            final String title = LanguageManager.get("weblaf.ex.dirchooser.delete.confirm.title");
            final int confirm =
                WebOptionPane.showConfirmDialog(
                    WebDirectoryChooserPanel.this,
                    message,
                    title,
                    WebOptionPane.YES_NO_OPTION,
                    WebOptionPane.QUESTION_MESSAGE);

            // Proceed if delete was confirmed
            if (confirm == WebOptionPane.YES_OPTION) {
              // Retrieving index of deleted file node in parent node
              final FileTreeNode parentNode = fileTree.getSelectedNode().getParent();
              final int index = parentNode.indexOfFileChild(file);
              final int count = parentNode.getChildCount();

              // Removing file
              FileUtils.deleteFile(file);
              fileTree.removeFile(file);

              // Restoring selection
              fileTree.setSelectedNode(
                  count == 1
                      ? parentNode
                      : (index < count - 1
                          ? parentNode.getChildAt(index)
                          : parentNode.getChildAt(index - 1)));
            }
          }
        });
    contolsToolbar.add(remove, ToolbarLayout.END);

    // Path field
    webPathField = new WebPathField(selectedDirectory);
    webPathField.setFileFilter(filter);
    webPathField.addPathFieldListener(
        new PathFieldListener() {
          @Override
          public void directoryChanged(final File newDirectory) {
            updateSelectedDirectory(webPathField.getSelectedPath(), false, true);
          }
        });

    // Files tree
    fileTree = new WebFileTree(FileTreeRootType.drives);
    fileTree.setVisibleRowCount(15);
    fileTree.setFileFilter(filter);
    fileTree.setSelectedFile(selectedDirectory, true);
    fileTree.setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
    fileTree.setEditable(true);

    // Selected directory update
    fileTreeListener =
        new TreeSelectionListener() {
          @Override
          public void valueChanged(final TreeSelectionEvent e) {
            updateSelectedDirectory(fileTree.getSelectedFile(), true, false);
          }
        };
    fileTree.addTreeSelectionListener(fileTreeListener);

    // Toolbar update
    fileTree.addTreeSelectionListener(
        new TreeSelectionListener() {
          @Override
          public void valueChanged(final TreeSelectionEvent e) {
            updateToolbarControlsState();
          }
        });

    // Tree scroll
    final WebScrollPane treeScroll = new WebScrollPane(fileTree);
    treeScroll.setPreferredWidth(400);

    // Panel content
    setLayout(new BorderLayout(0, 3));
    add(contolsToolbar, BorderLayout.NORTH);
    final WebPanel panel = new WebPanel(new BorderLayout(0, 1));
    panel.setMargin(0, 3, 2, 3);
    panel.add(webPathField, BorderLayout.NORTH);
    panel.add(treeScroll, BorderLayout.CENTER);
    add(panel, BorderLayout.CENTER);

    updateSelectedDirectory(null, true, true);
    updateToolbarControlsState();
  }

  /** Updates toolbar controls state. */
  protected void updateToolbarControlsState() {
    final File selectedFile = fileTree.getSelectedFile();

    folderUp.setEnabled(selectedFile != null && selectedFile.getParentFile() != null);

    folderNew.setEnabled(selectedFile != null && selectedFile.canWrite());
    remove.setEnabled(
        selectedFile != null && selectedFile.getParentFile() != null && selectedFile.canWrite());
  }

  /**
   * Updates currently selected directory.
   *
   * @param directory directory to select
   * @param updatePath whether to update path field or not
   * @param updateTree whether to update file tree or not
   */
  protected void updateSelectedDirectory(
      final File directory, final boolean updatePath, final boolean updateTree) {
    this.selectedDirectory = directory;

    if (updatePath) {
      webPathField.setSelectedPath(directory);
    }

    if (updateTree) {
      if (directory != null) {
        fileTree.expandToFile(
            directory,
            false,
            true,
            new Runnable() {
              @Override
              public void run() {
                fileTree.removeTreeSelectionListener(fileTreeListener);
                fileTree.setSelectedNode(fileTree.getNode(directory));
                fileTree.addTreeSelectionListener(fileTreeListener);
              }
            });
      } else {
        fileTree.clearSelection();
        fileTree.scrollToStart();
      }
    }

    fireSelectionChanged(this.selectedDirectory);
  }

  /**
   * Returns directory chooser file filter.
   *
   * @return directory chooser file filter
   */
  public AbstractFileFilter getFilter() {
    return filter;
  }

  /**
   * Sets directory chooser file filter.
   *
   * @param filter directory chooser file filter
   */
  public void setFilter(final AbstractFileFilter filter) {
    this.filter = filter;
    fileTree.setFileFilter(filter);
  }

  /**
   * Returns currently selected directory.
   *
   * @return currently selected directory
   */
  public File getSelectedDirectory() {
    return selectedDirectory;
  }

  /**
   * Sets currently selected directory.
   *
   * @param selectedDirectory currently selected directory
   */
  public void setSelectedDirectory(final File selectedDirectory) {
    updateSelectedDirectory(selectedDirectory, true, true);
  }

  /**
   * Returns whether hotkeys are allowed or not.
   *
   * @return true if hotkeys are allowed, false otherwise
   */
  public boolean allowHotkeys() {
    // todo Remove this when hotkeys system will get updated
    return !fileTree.isEditing() && !webPathField.isEditing() /*&& !fileList.isEditing()*/;
  }

  /**
   * Adds directory chooser listener.
   *
   * @param listener directory chooser listener to add
   */
  public void addDirectoryChooserListener(final DirectoryChooserListener listener) {
    listeners.add(listener);
  }

  /**
   * Removes directory chooser listener.
   *
   * @param listener directory chooser listener to remove
   */
  public void removeDirectoryChooserListener(final DirectoryChooserListener listener) {
    listeners.remove(listener);
  }

  /**
   * Fires when directory selection changed.
   *
   * @param file newly selected directory
   */
  protected void fireSelectionChanged(final File file) {
    for (final DirectoryChooserListener listener : CollectionUtils.copy(listeners)) {
      listener.selectionChanged(file);
    }
  }
}