public void paintComponent(Graphics g) {

    super.paintComponent(g);

    if (SnapshotGallery.sharedInstance().isEmpty()) {
      FontMetrics fm = g.getFontMetrics();
      String s = Modeler.getInternationalText("NoSnapshotAvailable");
      if (s == null) s = "No snapshot is available.";
      g.drawString(s, (getWidth() - fm.stringWidth(s)) / 2, (getHeight() - fm.getHeight()) / 2);
      return;
    }

    float w, h;
    Insets insets = getInsets();
    int x = insets.left;
    int n = SnapshotGallery.sharedInstance().size();
    Image image;
    for (int i = n - 1; i >= 0; i--) {
      image = SnapshotGallery.sharedInstance().getThumbnail(i);
      if (image == null) continue;
      w = image.getWidth(this);
      h = image.getHeight(this);
      w *= IMAGE_HEIGHT / h;
      if (i == SnapshotGallery.sharedInstance().getSelectedIndex()) {
        g.setColor(Color.red);
        g.drawRect(x - 3, insets.top - 3, (int) w + 6, IMAGE_HEIGHT + 6);
        g.drawRect(x - 2, insets.top - 2, (int) w + 4, IMAGE_HEIGHT + 4);
      }
      g.drawImage(image, x, insets.top, this);
      if (getLayout() instanceof FlowLayout) {
        x += (int) w + ((FlowLayout) getLayout()).getHgap();
      } else {
        x += (int) w + IMAGE_GAP;
      }
    }
  }
  private void createContentPane() {

    if (contentPane != null) return;

    contentPane = new JPanel(new BorderLayout());

    ActionListener okListener =
        new ActionListener() {
          public void actionPerformed(ActionEvent e) {
            if (confirm()) {
              dialog.dispose();
              cancel = false;
            }
          }
        };

    JPanel p = new JPanel(new FlowLayout(FlowLayout.RIGHT));
    contentPane.add(p, BorderLayout.SOUTH);

    String s = Modeler.getInternationalText("OKButton");
    okButton = new JButton(s != null ? s : "OK");
    okButton.addActionListener(okListener);
    p.add(okButton);

    s = Modeler.getInternationalText("CancelButton");
    JButton button = new JButton(s != null ? s : "Cancel");
    button.addActionListener(
        new ActionListener() {
          public void actionPerformed(ActionEvent e) {
            dialog.setVisible(false);
            cancel = true;
          }
        });
    p.add(button);

    s = Modeler.getInternationalText("Help");
    button = new JButton(s != null ? s : "Help");
    button.addActionListener(
        new ActionListener() {
          public void actionPerformed(ActionEvent e) {
            Modeler.openWithNewInstance(
                pageCheckBox.getPage().getNavigator().getHomeDirectory()
                    + "tutorial/insertCheckBox.cml");
          }
        });
    p.add(button);

    p = new JPanel(new SpringLayout());
    p.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
    contentPane.add(p, BorderLayout.NORTH);

    // row 1
    s = Modeler.getInternationalText("SelectModelLabel");
    p.add(new JLabel(s != null ? s : "Select a model", SwingConstants.LEFT));
    modelComboBox = new JComboBox();
    if (smallFont == null)
      smallFont =
          new Font(modelComboBox.getFont().getFamily(), modelComboBox.getFont().getStyle(), 10);
    modelComboBox.setFont(smallFont);
    modelComboBox.setRenderer(new LabelRenderer());
    modelComboBox.setPreferredSize(new Dimension(200, 20));
    modelComboBox.setToolTipText(
        "If there are multiple models on the page, select the one this check box will interact with.");
    p.add(modelComboBox);

    // row 2
    s = Modeler.getInternationalText("SelectActionLabel");
    p.add(new JLabel(s != null ? s : "Select an action", SwingConstants.LEFT));
    actionComboBox = new JComboBox();
    actionComboBox.setFont(smallFont);
    actionComboBox.setToolTipText("Select the switching action for this check box.");
    p.add(actionComboBox);

    // row 3
    s = Modeler.getInternationalText("UniqueIdentifier");
    p.add(new JLabel(s != null ? s : "Unique identifier", SwingConstants.LEFT));
    uidField = new JTextField();
    uidField.setToolTipText(
        "Type in a string to be used as the unique identifier of this check box.");
    uidField.addActionListener(okListener);
    p.add(uidField);

    // row 4
    s = Modeler.getInternationalText("TextLabel");
    p.add(new JLabel(s != null ? s : "Text", SwingConstants.LEFT));
    nameField = new JTextField();
    nameField.setToolTipText("Type in the text that will appear on this check box.");
    nameField.addActionListener(okListener);
    p.add(nameField);

    // row 5
    s = Modeler.getInternationalText("ImageFileNameSelected");
    p.add(new JLabel(s != null ? s : "Image to show while selected", SwingConstants.LEFT));
    imageSelectedField = new JTextField();
    imageSelectedField.setToolTipText(
        "Type in the file name of the image that will appear on this check box while it is selected.");
    imageSelectedField.addActionListener(okListener);
    p.add(imageSelectedField);

    // row 6
    s = Modeler.getInternationalText("ImageFileNameDeselected");
    p.add(new JLabel(s != null ? s : "Image to show while not selected", SwingConstants.LEFT));
    imageDeselectedField = new JTextField();
    imageDeselectedField.setToolTipText(
        "Type in the file name of the image that will appear on this check box while it is not selected.");
    imageDeselectedField.addActionListener(okListener);
    p.add(imageDeselectedField);

    // row 7
    s = Modeler.getInternationalText("ToolTipLabel");
    p.add(new JLabel(s != null ? s : "Tool tip", SwingConstants.LEFT));
    toolTipField = new JTextField();
    toolTipField.setToolTipText("Type in the text that will appear as the tool tip.");
    toolTipField.addActionListener(okListener);
    p.add(toolTipField);

    // row 8
    s = Modeler.getInternationalText("WidthLabel");
    p.add(new JLabel(s != null ? s : "Width", SwingConstants.LEFT));
    widthField =
        new IntegerTextField(pageCheckBox.getWidth() <= 0 ? 100 : pageCheckBox.getWidth(), 10, 400);
    widthField.setEnabled(false);
    widthField.setToolTipText(
        "Type in an integer to set the width of this check box, if it will not be auto-sized.");
    widthField.addActionListener(okListener);
    p.add(widthField);

    // row 9
    s = Modeler.getInternationalText("HeightLabel");
    p.add(new JLabel(s != null ? s : "Height", SwingConstants.LEFT));
    heightField =
        new IntegerTextField(
            pageCheckBox.getHeight() <= 0 ? 24 : pageCheckBox.getHeight(), 10, 400);
    heightField.setEnabled(false);
    heightField.setToolTipText(
        "Type in an integer to set the height of this check box, if it will not be auto-sized.");
    heightField.addActionListener(okListener);
    p.add(heightField);

    // row 10
    s = Modeler.getInternationalText("BackgroundColorLabel");
    p.add(new JLabel(s != null ? s : "Background color", SwingConstants.LEFT));
    bgComboBox = new ColorComboBox(pageCheckBox);
    bgComboBox.setRequestFocusEnabled(false);
    bgComboBox.setToolTipText(
        "Select the background color for this check box, if it is not transparent.");
    p.add(bgComboBox);

    ModelerUtilities.makeCompactGrid(p, 10, 2, 5, 5, 10, 2);

    p = new JPanel(new BorderLayout(10, 10));
    p.setBorder(BorderFactory.createEmptyBorder(2, 10, 2, 10));
    contentPane.add(p, BorderLayout.CENTER);

    JPanel p1 = new JPanel(new GridLayout(2, 2));
    p1.setBorder(BorderFactory.createEtchedBorder());
    p.add(p1, BorderLayout.NORTH);

    s = Modeler.getInternationalText("TransparencyCheckBox");
    transparentCheckBox = new JCheckBox(s != null ? s : "Transparent");
    // transparentCheckBox.setEnabled(!Page.isNativeLookAndFeelUsed());
    transparentCheckBox.setSelected(false);
    transparentCheckBox.setToolTipText("Select to set this check box to be transparent.");
    p1.add(transparentCheckBox);

    s = Modeler.getInternationalText("AutosizeCheckBox");
    autoSizeCheckBox = new JCheckBox(s != null ? s : "Size automatically");
    autoSizeCheckBox.setSelected(pageCheckBox.autoSize);
    autoSizeCheckBox.setToolTipText(
        "<html>Select to make this check box auto-size itself according to the text and image on it.<br>Deselect to set a custom size.</html>");
    autoSizeCheckBox.addItemListener(
        new ItemListener() {
          public void itemStateChanged(ItemEvent e) {
            pageCheckBox.autoSize = autoSizeCheckBox.isSelected();
            widthField.setEnabled(!pageCheckBox.autoSize);
            heightField.setEnabled(!pageCheckBox.autoSize);
          }
        });
    p1.add(autoSizeCheckBox);

    s = Modeler.getInternationalText("DisabledAtRunCheckBox");
    disabledAtRunCheckBox = new JCheckBox(s != null ? s : "Disabled while model is running");
    disabledAtRunCheckBox.setSelected(false);
    disabledAtRunCheckBox.setToolTipText(
        "<html>Select if you wish this check box to be disabled while the model is running,<br>and to be enabled when the model stops.</html>");
    p1.add(disabledAtRunCheckBox);

    s = Modeler.getInternationalText("DisabledAtScriptCheckBox");
    disabledAtScriptCheckBox = new JCheckBox(s != null ? s : "Disabled while scripts are running");
    disabledAtScriptCheckBox.setSelected(false);
    disabledAtScriptCheckBox.setToolTipText(
        "<html>Select if you wish this check box to be disabled while scripts are running,<br>and to be enabled when scripts end.</html>");
    p1.add(disabledAtScriptCheckBox);

    p1 = new JPanel(new GridLayout(2, 1, 5, 5));
    p.add(p1, BorderLayout.CENTER);

    JPanel p2 = new JPanel(new BorderLayout(5, 5));
    s = Modeler.getInternationalText("EnterScriptWhenSelectedLabel");
    scriptLabelSelected = new JLabel(s != null ? s : "Enter the script to be run when selected:");
    scriptLabelSelected.setEnabled(false);
    p2.add(scriptLabelSelected, BorderLayout.NORTH);
    scriptAreaSelected = new PastableTextArea(5, 10);
    scriptAreaSelected.setEnabled(false);
    scriptAreaSelected.setBorder(BorderFactory.createLoweredBevelBorder());
    p2.add(new JScrollPane(scriptAreaSelected), BorderLayout.CENTER);
    p1.add(p2);

    p2 = new JPanel(new BorderLayout(5, 5));
    s = Modeler.getInternationalText("EnterScriptWhenDeselectedLabel");
    scriptLabelDeselected =
        new JLabel(s != null ? s : "Enter the script to be run when deselected:");
    scriptLabelDeselected.setEnabled(false);
    p2.add(scriptLabelDeselected, BorderLayout.NORTH);
    scriptAreaDeselected = new PastableTextArea(5, 10);
    scriptAreaDeselected.setEnabled(false);
    scriptAreaDeselected.setBorder(BorderFactory.createLoweredBevelBorder());
    p2.add(new JScrollPane(scriptAreaDeselected), BorderLayout.CENTER);
    p1.add(p2);
  }
  void invoke(Page page) {

    pageCheckBox.page = page;
    page.deselect();
    createContentPane();

    if (needNewDialog(dialog, page)) {
      String s = Modeler.getInternationalText("CustomizeCheckBoxDialogTitle");
      dialog = ModelerUtilities.getChildDialog(page, s != null ? s : "Customize check box", true);
      dialog.setContentPane(contentPane);
      dialog.pack();
      dialog.setLocationRelativeTo(dialog.getOwner());
      dialog.addWindowListener(
          new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
              cancel = true;
              dialog.setVisible(false);
            }

            public void windowActivated(WindowEvent e) {
              nameField.selectAll();
              nameField.requestFocusInWindow();
            }
          });
    }

    modelComboBox.removeItemListener(modelSelectionListener);
    modelComboBox.removeAllItems();
    actionComboBox.removeItemListener(actionSelectionListener);

    // add legacy MD models to the model list
    final ComponentPool componentPool = page.getComponentPool();
    synchronized (componentPool) {
      for (ModelCanvas mc : componentPool.getModels()) {
        if (mc.isUsed()) {
          modelComboBox.addItem(mc.getMdContainer().getModel());
        }
      }
    }

    // add target models to the model list
    for (Class c : ModelCommunicator.targetClass) {
      Map map = page.getEmbeddedComponent(c);
      if (map != null && !map.isEmpty()) {
        for (Object o : map.keySet()) {
          modelComboBox.addItem(map.get(o));
        }
      }
    }

    if (pageCheckBox.isTargetClass()) {
      if (pageCheckBox.modelID != -1) {
        try {
          Object o =
              page.getEmbeddedComponent(
                  Class.forName(pageCheckBox.modelClass), pageCheckBox.modelID);
          if (o != null) modelComboBox.setSelectedItem(o);
        } catch (ClassNotFoundException e) {
          e.printStackTrace();
        }
      } else {
        BasicModel m = (BasicModel) modelComboBox.getSelectedItem();
        if (m instanceof Embeddable) pageCheckBox.setModelID(((Embeddable) m).getIndex());
      }
    } else {
      if (pageCheckBox.modelID != -1) {
        ModelCanvas mc = componentPool.get(pageCheckBox.modelID);
        modelComboBox.setSelectedItem(mc.getMdContainer().getModel());
      } else {
        BasicModel m = (BasicModel) modelComboBox.getSelectedItem();
        pageCheckBox.setModelID(componentPool.getIndex(m));
      }
    }
    modelComboBox.addItemListener(modelSelectionListener);

    fillActionComboBox();
    if (pageCheckBox.getAction() != null) actionComboBox.setSelectedItem(pageCheckBox.getAction());
    actionComboBox.addItemListener(actionSelectionListener);

    String t = pageCheckBox.getText();
    nameField.setText(
        t != null
            ? t
            : (actionComboBox.getSelectedItem() != null
                ? actionComboBox.getSelectedItem().toString()
                : null));
    uidField.setText(pageCheckBox.getUid());
    imageSelectedField.setText(pageCheckBox.getImageFileNameSelected());
    imageDeselectedField.setText(pageCheckBox.getImageFileNameDeselected());
    toolTipField.setText(pageCheckBox.getToolTipText());
    transparentCheckBox.setSelected(pageCheckBox.isTransparent());
    disabledAtRunCheckBox.setSelected(pageCheckBox.disabledAtRun);
    disabledAtScriptCheckBox.setSelected(pageCheckBox.disabledAtScript);
    bgComboBox.setColor(pageCheckBox.getBackground());
    autoSizeCheckBox.setSelected(pageCheckBox.autoSize);
    if (pageCheckBox.isPreferredSizeSet()) {
      widthField.setValue(pageCheckBox.getWidth());
      heightField.setValue(pageCheckBox.getHeight());
    }
    widthField.setEnabled(!pageCheckBox.autoSize);
    heightField.setEnabled(!pageCheckBox.autoSize);
    okButton.setEnabled(modelComboBox.getItemCount() > 0 && actionComboBox.getItemCount() > 0);

    setScriptArea();

    dialog.setVisible(true);
  }