private static Component createDescription(Example example, ExampleGroup group) {
    Color foreground = group.getPreferredForeground();

    WebLabel titleLabel = new WebLabel(example.getTitle(), JLabel.TRAILING);
    titleLabel.setDrawShade(true);
    titleLabel.setForeground(foreground);
    if (foreground.equals(Color.WHITE)) {
      titleLabel.setShadeColor(Color.BLACK);
    }

    if (example.getDescription() == null) {
      return titleLabel;
    } else {
      WebLabel descriptionLabel = new WebLabel(example.getDescription(), WebLabel.TRAILING);
      descriptionLabel.setForeground(Color.GRAY);
      SwingUtils.changeFontSize(descriptionLabel, -1);

      WebPanel vertical =
          new WebPanel(new VerticalFlowLayout(VerticalFlowLayout.MIDDLE, 0, 0, true, false));
      vertical.setOpaque(false);
      vertical.add(titleLabel);
      vertical.add(descriptionLabel);

      return vertical;
    }
  }
  public static WebTabbedPane createExampleTabs(WebLookAndFeelDemo owner, WebProgressDialog load) {
    // All example groups
    load.setText("Loading groups list");
    List<ExampleGroup> exampleGroups = getExampleGroups();
    load.setMinimum(0);
    load.setMaximum(exampleGroups.size() + 1);
    load.setProgress(0);

    // Example tabs
    WebTabbedPane exampleTabs = new WebTabbedPane();
    exampleTabs.setTabbedPaneStyle(TabbedPaneStyle.attached);
    // exampleTabs.setTabLayoutPolicy ( WebTabbedPane.SCROLL_TAB_LAYOUT );

    // Progress component
    IconProgress ip = (IconProgress) load.getMiddleComponent();

    // Creating all examples
    int progress = 1;
    for (ExampleGroup group : exampleGroups) {
      // Updating progress state
      load.setText("Loading group: " + group.getGroupName());
      load.setProgress(progress);
      progress++;

      // Updating progress icons
      Icon gi = group.getGroupIcon();
      ip.addLoadedElement(gi);

      // Adding group view to new tab
      exampleTabs.addTab(group.getGroupName(), gi, createGroupView(owner, group));

      // Applying foreground settings
      exampleTabs.setSelectedForegroundAt(
          exampleTabs.getTabCount() - 1, group.getPreferredForeground());

      // Applying specific group settings to tab
      group.modifyExampleTab(exampleTabs.getTabCount() - 1, exampleTabs);
    }
    load.setProgress(progress);

    return exampleTabs;
  }
  public static Component createGroupView(WebLookAndFeelDemo owner, ExampleGroup group) {
    // Creating group view
    Component exampleView;
    List<Example> examples = group.getGroupExamples();
    if (group.isSingleExample() && examples.size() == 1) {
      Example example = examples.get(0);
      exampleView = example.getPreview(owner);
    } else {
      final List<Component> preview = new ArrayList<Component>();

      final WebPanel groupPanel =
          new WebPanel() {
            @Override
            public void setEnabled(boolean enabled) {
              for (Component previewComponent : preview) {
                SwingUtils.setEnabledRecursively(previewComponent, enabled);
              }
              super.setEnabled(enabled);
            }
          };
      groupPanel.putClientProperty(SwingUtils.HANDLES_ENABLE_STATE, true);
      groupPanel.setOpaque(false);
      exampleView = groupPanel;

      int rowsAmount = examples.size() > 1 ? examples.size() * 2 - 1 : 1;
      double[] rows = new double[6 + rowsAmount];
      rows[0] = TableLayout.FILL;
      rows[1] = 20;
      rows[2] = TableLayout.PREFERRED;
      for (int i = 3; i < rows.length - 3; i++) {
        rows[i] = TableLayout.PREFERRED;
      }
      rows[rows.length - 3] = TableLayout.PREFERRED;
      rows[rows.length - 2] = 20;
      rows[rows.length - 1] = TableLayout.FILL;

      double[] columns = {
        20,
        1f - group.getContentPartSize(),
        TableLayout.PREFERRED,
        TableLayout.PREFERRED,
        TableLayout.PREFERRED,
        TableLayout.PREFERRED,
        TableLayout.PREFERRED,
        TableLayout.PREFERRED,
        TableLayout.PREFERRED,
        group.getContentPartSize(),
        20
      };

      TableLayout groupLayout = new TableLayout(new double[][] {columns, rows});
      groupLayout.setHGap(4);
      groupLayout.setVGap(4);
      groupPanel.setLayout(groupLayout);

      groupPanel.add(
          group.modifySeparator(createVerticalSeparator()), "2,0,2," + (rows.length - 1));
      groupPanel.add(
          group.modifySeparator(createVerticalSeparator()), "4,0,4," + (rows.length - 1));
      groupPanel.add(
          group.modifySeparator(createVerticalSeparator()), "6,0,6," + (rows.length - 1));
      groupPanel.add(
          group.modifySeparator(createVerticalSeparator()), "8,0,8," + (rows.length - 1));

      groupPanel.add(
          group.modifySeparator(createHorizontalSeparator()), "0,2," + (columns.length - 1) + ",2");
      groupPanel.add(
          group.modifySeparator(createHorizontalSeparator()),
          "0," + (rows.length - 3) + "," + (columns.length - 1) + "," + (rows.length - 3));

      int row = 3;
      for (Example example : examples) {
        // Title & description
        groupPanel.add(createDescription(example, group), "1," + row);

        // Marks
        Component mark = createMark(owner, example);
        groupPanel.add(mark, "3," + row);

        // Source code
        Component source = createSourceButton(owner, example);
        groupPanel.add(source, "5," + row);

        // More usage examples
        Component usage = createPresentationButton(example);
        groupPanel.add(usage, "7," + row);

        SwingUtils.equalizeComponentsSize(mark, source, usage);

        // Preview
        Component previewComponent = createPreview(owner, example);
        groupPanel.add(previewComponent, "9," + row);
        preview.add(previewComponent);

        // Rows separator
        if (row > 3) {
          groupPanel.add(
              group.modifySeparator(createHorizontalSeparator()),
              "0," + (row - 1) + "," + (columns.length - 1) + "," + (row - 1),
              0);
        }

        row += 2;
      }
    }

    if (group.isShowWatermark()) {
      WebImage linkImage = new WebImage(logoIcon);
      linkImage.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));

      TooltipManager.setTooltip(linkImage, linkIcon, "Library site", TooltipWay.trailing);

      linkImage.addMouseListener(
          new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
              WebUtils.browseSiteSafely(WebLookAndFeelDemo.WEBLAF_SITE);
            }
          });

      WebOverlay linkOverlay =
          new WebOverlay(exampleView, linkImage, WebOverlay.LEADING, WebOverlay.BOTTOM);
      linkOverlay.setOverlayMargin(15, 15, 15, 15);
      linkOverlay.setOpaque(false);

      exampleView = linkOverlay;
    }

    return exampleView;
  }
  public static JarStructure createJarStructure(final WebProgressDialog progress) {
    // Download listener in case of remote jar-file (for e.g. demo loaded from .jnlp)
    FileDownloadListener listener =
        new FileDownloadListener() {
          private int totalSize = 0;

          @Override
          public void sizeDetermined(int totalSize) {
            // Download started
            this.totalSize = totalSize;
            updateProgress(0);
          }

          @Override
          public void partDownloaded(int totalBytesDownloaded) {
            // Some part loaded
            updateProgress(totalBytesDownloaded);
          }

          @Override
          public boolean shouldStopDownload() {
            return false;
          }

          private void updateProgress(int downloaded) {
            // Updating progress text
            progress.setText(
                "<html>Loading source files... <b>"
                    + FileUtils.getFileSizeString(downloaded, 1)
                    + "</b> of <b>"
                    + FileUtils.getFileSizeString(totalSize, 1)
                    + "</b> done</html>");
          }

          @Override
          public void fileDownloaded(File file) {
            // Updating progress text
            progress.setText("Creating source files structure...");
          }

          @Override
          public void fileDownloadFailed(Throwable e) {
            // Updating progress text
            progress.setText("Filed to download source files");
          }
        };

    // Creating structure using any of classes contained inside jar
    progress.setText("Creating source files structure...");
    List<String> extensions = Arrays.asList(".java", ".png", ".gif", ".jpg", ".txt", ".xml");
    List<String> packages = Arrays.asList("com/alee", "licenses");
    JarStructure jarStructure =
        ReflectUtils.getJarStructure(ExamplesManager.class, extensions, packages, listener);

    // Updating some of package icons
    jarStructure.setPackageIcon(
        WebLookAndFeelDemo.class.getPackage(), new ImageIcon(WebLookAndFeel.getImages().get(0)));
    for (ExampleGroup exampleGroup : getExampleGroups()) {
      jarStructure.setClassIcon(exampleGroup.getClass(), (ImageIcon) exampleGroup.getGroupIcon());
    }

    return jarStructure;
  }