Package

Source Code of Main

import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.prefs.Preferences;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.SpringLayout;
import javax.swing.UIManager;
import javax.swing.filechooser.FileFilter;

public class Main {

  public static final int APPLICATION_VERSION = 1;

  protected static final strings S = new strings();
  private static final String DS = "/"; // Directory separator
  protected static Integer JSKY_DEFAULT_PADDING = 7;
  protected static Integer PREFFERED_WIDTH = 485;
  protected static Integer PREFFERED_HEIGHT = 500;

  protected static File wow_path;
  protected static File wtf_path; // determined later by "wow_path", if known.
  protected static File accs_path;// determined later by "wow_path", if known.
  protected static final String AddonLuaFileName = "BankerkaBags.lua";
  protected static final Integer TARGET_BANKERKABAGS_LUA_VERSION = 1;
  protected static final String BB_DEFAULT_ENCODING = "UTF-8";

  private static final String WEB_ACTION_UPDATE = "update";

  // protected static String TARGET_HOST_URL =
  // "http://myjursky.php5.sk/bankerkabags/";
  protected static String TARGET_HOST_URL = "http://localhost/bankerkabags/";

  protected static Preferences cfg = Preferences
      .userNodeForPackage(Main.class);

  protected static JFrame mainWindowFrm = new JFrame(S.APPNAME);
  protected static ArrayList<File> charsLuasToSync = new ArrayList<>();

  protected static ArrayList<WowCharacter> wowCharacters = new ArrayList<>();

  public static void main(String[] args) {
    mainWindowFrm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setDefaultFonts();
    updatePanels();
  }

  private static void setDefaultFonts() {
    Font appDefaultFont = new Font("Verdana", Font.PLAIN, 11);
    UIManager.put("Button.font", appDefaultFont);
    UIManager.put("ToggleButton.font", appDefaultFont);
    UIManager.put("RadioButton.font", appDefaultFont);
    UIManager.put("CheckBox.font", appDefaultFont);
    UIManager.put("ColorChooser.font", appDefaultFont);
    UIManager.put("ComboBox.font", appDefaultFont);
    UIManager.put("Label.font", appDefaultFont);
    UIManager.put("List.font", appDefaultFont);
    UIManager.put("MenuBar.font", appDefaultFont);
    UIManager.put("MenuItem.font", appDefaultFont);
    UIManager.put("RadioButtonMenuItem.font", appDefaultFont);
    UIManager.put("CheckBoxMenuItem.font", appDefaultFont);
    UIManager.put("Menu.font", appDefaultFont);
    UIManager.put("PopupMenu.font", appDefaultFont);
    UIManager.put("OptionPane.font", appDefaultFont);
    UIManager.put("Panel.font", appDefaultFont);
    UIManager.put("ProgressBar.font", appDefaultFont);
    UIManager.put("ScrollPane.font", appDefaultFont);
    UIManager.put("Viewport.font", appDefaultFont);
    UIManager.put("TabbedPane.font", appDefaultFont);
    UIManager.put("Table.font", appDefaultFont);
    UIManager.put("TableHeader.font", appDefaultFont);
    UIManager.put("TextField.font", appDefaultFont);
    UIManager.put("PasswordField.font", appDefaultFont);
    UIManager.put("TextArea.font", appDefaultFont);
    UIManager.put("TextPane.font", appDefaultFont);
    UIManager.put("EditorPane.font", appDefaultFont);
    UIManager
        .put("TitledBorder.font", appDefaultFont.deriveFont(Font.BOLD));
    UIManager.put("ToolBar.font", appDefaultFont);
    UIManager.put("ToolTip.font", appDefaultFont);
    UIManager.put("Tree.font", appDefaultFont);
  }

  static JPanel createPanel_wowExeLocChoose() {
    JPanel wowChoosePnl = new JPanel();
    wowChoosePnl.setBorder(BorderFactory
        .createTitledBorder(S.WOW_EXE_FILE_LOCATION_SELECTION));

    // World of WarCraft installment location choose panel
    final JTextField wowExeLocTxtFld = new JTextField();
    if (cfg != null && cfg.get("WOW_EXE_LOCATION", null) != null) {
      // If we know WoW directory, set-up variables for WTF subdirectories
      // (accs, chars, ..)
      wow_path = new File(cfg.get("WOW_EXE_LOCATION", ""));
      // TODO: sub-directory paths
      wtf_path = new File(wow_path.getAbsolutePath() + DS + "WTF");
      accs_path = new File(wtf_path.getAbsolutePath() + DS + "Account");
      wowExeLocTxtFld.setText(wow_path.getAbsolutePath());
    }
    wowExeLocTxtFld.setColumns(30);
    wowExeLocTxtFld.setEnabled(false);
    wowChoosePnl.add(wowExeLocTxtFld);

    JButton wowExeLocBttn = new JButton(S.BROWSE_FILE);
    wowExeLocBttn.addActionListener(new ActionListener() {

      @Override
      public void actionPerformed(ActionEvent e) {
        JFileChooser wowExeLocFlChsr = new JFileChooser();
        if (wow_path != null) {
          File wowExeFile = (wow_path);
          if (wowExeFile.exists())
            wowExeLocFlChsr.setCurrentDirectory(wowExeFile);
        }
        wowExeLocFlChsr
            .setDialogTitle(S.WOW_EXE_FILE_LOCATION_SELECTION);
        wowExeLocFlChsr.setFileFilter(new FileFilter() {

          @Override
          public String getDescription() {
            return "wow.exe, launcher.exe";
          }

          @Override
          public boolean accept(File arg0) {
            return arg0.isDirectory()
                || arg0.getName().equalsIgnoreCase("wow.exe")
                || arg0.getName().toLowerCase()
                    .equalsIgnoreCase("launcher.exe");
          }
        });
        int result = wowExeLocFlChsr.showOpenDialog(null);
        switch (result) {
        case JFileChooser.APPROVE_OPTION: {
          String n = wowExeLocFlChsr.getSelectedFile().getName();
          if (n.length() == 0
              || (!n.equalsIgnoreCase("wow.exe") && !n
                  .equalsIgnoreCase("laucher.exe"))) {
            // TODO: remove "wrong file" popup? I think it should be
            // there, but what if someone is starting World of
            // Warcraft somehow else than by default way?
            // JOptionPane.showMessageDialog(new JFrame(),
            // S.WRONG_FILE_SELECTED_FULL + ".");
            if (1 == JOptionPane.showConfirmDialog(
                mainWindowFrm,
                String.format(
                    "<html><p style='width: 400px;'>%s.</p></html>",
                    S.WRONG_FILE_SELECTED_FULL
                        + ". "
                        + S.HOWEVER_WOULD_YOU_STILL_LIKE_TO_USE_THIS_FILE
                        + " "
                        + S.PROGRAM_MAY_NOT_WORK_PROPERLY),
                S.WRONG_FILE_SELECTED,
                JOptionPane.YES_NO_OPTION))
              break;
          }

          String wowExeFullLoc = wowExeLocFlChsr.getSelectedFile()
              .getAbsolutePath();
          wowExeFullLoc = wowExeFullLoc.substring(0,
              wowExeFullLoc.lastIndexOf(File.separator));
          wowExeLocTxtFld.setText(wowExeFullLoc);
          cfg.put("WOW_EXE_LOCATION", wowExeFullLoc);
          updatePanels();
          break;
        }
        }
      }
    });
    wowChoosePnl.add(wowExeLocBttn);
    return wowChoosePnl;
  }

  static JPanel createPanel_wowCharactersSelection() {
    JPanel wowCharsSelPnl = new JPanel(new GridBagLayout());
    GridBagConstraints c = new GridBagConstraints();
    c.fill = GridBagConstraints.HORIZONTAL;
    c.gridx = 0;
    c.gridy = 0;

    wowCharsSelPnl.setBorder(BorderFactory
        .createTitledBorder(S.WOW_CHARACTERS_SELECTION));

    if (wow_path != null) {
      JPanel accsChckBoxesPnl = new JPanel(new GridBagLayout());
      GridBagConstraints accsChckBoxesPnl_c = new GridBagConstraints();
      accsChckBoxesPnl_c.fill = GridBagConstraints.HORIZONTAL;
      accsChckBoxesPnl_c.gridx = 0;
      accsChckBoxesPnl_c.gridy = 0;
      // Look for available accounts and its saved variables
      try {
        File[] accountsDirs = (accs_path).listFiles();

        String charsSelTxt = S.SELECT_CHARS_TO_SYNC;

        if (accountsDirs == null) {
          charsSelTxt = S.NO_CHARACTERS_AVAILABLE
              + ". "
              + S.PLEASE_MAKE_SURE_YOU_SELECTED_PROPER_WOW_DIR
              + ". "
              + String.format("%s. %s",
                  S.MAKE_SURE_YOU_HAVE_ACCESS_TO_DIR,
                  S.ADMINISTRATOR_PRIVILEGIES_MAY_BE_REQUIRED);
        }

        wowCharsSelPnl
            .add(new JLabel(
                String.format(
                    "<html><div style='width: 337px; padding: 5px; text-align: justify;'>%s.</div></html>",
                    charsSelTxt)), c);

        if (accountsDirs == null)
          return wowCharsSelPnl;

        for (final File accDir : accountsDirs) {
          // dout(accDir.getName(), true);

          final JPanel accCharsPnl = new JPanel();
          accCharsPnl.setLayout(new GridBagLayout());
          GridBagConstraints accCharsPnl_c = new GridBagConstraints();
          accCharsPnl_c.fill = GridBagConstraints.HORIZONTAL;
          accCharsPnl_c.gridy = 0;
          accCharsPnl.setBorder(BorderFactory
              .createTitledBorder(S.ACCOUNT + " "
                  + accDir.getName()));

          final JCheckBox accEnabledChkbox = new JCheckBox(S.SYNC
              + " " + S.FOR.toLowerCase() + " "
              + accDir.getName() + " " + S.ENABLED.toLowerCase());
          accEnabledChkbox.setSelected(cfg.getBoolean(
              "AccountAllowance_" + accDir.getName(), false));
          accEnabledChkbox.addItemListener(new ItemListener() {

            @Override
            public void itemStateChanged(ItemEvent e) {
              if (e.getStateChange() == ItemEvent.SELECTED
                  || e.getStateChange() == ItemEvent.DESELECTED) {
                boolean chkbox_enabled = e.getStateChange() == ItemEvent.SELECTED;

                cfg.putBoolean(
                    "AccountAllowance_" + accDir.getName(),
                    chkbox_enabled);

                // Disable all JCheckBox subcomponents
                // (account'� characters allowance).
                Component[] cmps = accCharsPnl.getComponents();
                for (Component cmp : cmps) {
                  // We want only JCheckBox(es).
                  if (!(cmp instanceof JCheckBox)
                      || cmp == accEnabledChkbox)
                    continue;

                  JCheckBox jchkbox = ((JCheckBox) cmp);
                  jchkbox.setEnabled(chkbox_enabled);
                  for (ItemListener il : ((JCheckBox) cmp)
                      .getItemListeners()) {
                    int oldState = jchkbox.isSelected() ? ItemEvent.SELECTED
                        : ItemEvent.DESELECTED;
                    ItemEvent fakeItemEvent = new ItemEvent(
                        accEnabledChkbox,
                        ItemEvent.ITEM_STATE_CHANGED,
                        jchkbox,
                        !chkbox_enabled ? ItemEvent.DESELECTED
                            : oldState);
                    il.itemStateChanged(fakeItemEvent);
                  }
                }
              }
            }
          });
          accCharsPnl.add(accEnabledChkbox, accCharsPnl_c);
          ++accCharsPnl_c.gridy;

          // Look for Account's servers
          File[] accServersDirs = accDir
              .listFiles(new java.io.FileFilter() {

                @Override
                public boolean accept(File arg0) {
                  return arg0.isDirectory()
                      && !arg0.getName().equals(
                          "SavedVariables");
                }
              });
          for (final File serverDir : accServersDirs) {
            File[] serverCharsDirs = serverDir
                .listFiles(new java.io.FileFilter() {

                  @Override
                  public boolean accept(File arg0) {
                    // FIXME: make straight checking for
                    // BankerkasBags.lua file?
                    File charAddonLuaFile = new File(arg0
                        .getAbsolutePath()
                        + DS
                        + "SavedVariables"
                        + DS
                        + AddonLuaFileName);
                    return arg0.isDirectory()
                        && charAddonLuaFile.exists();
                  }
                });
            for (final File charDir : serverCharsDirs) {
              // Add current character to list for sync (create
              // new character object and put it to the list among
              // the others).
              final WowCharacter wowChar = new WowCharacter(
                  charDir.getName(), new File(
                      charDir.getAbsoluteFile() + DS
                          + "SavedVariables" + DS
                          + AddonLuaFileName));

              // Populate Char's inventory.
              // wowChar.populateBagsItems(); // TODO: not needed
              // now..

              JCheckBox charAllowanceChkbox = new JCheckBox(
                  charDir.getName() + " ("
                      + serverDir.getName() + ")");
              charAllowanceChkbox.setEnabled(accEnabledChkbox
                  .isSelected());
              boolean isWowCharChkboxSelected = cfg.getBoolean(
                  "CharacterAllowance_" + serverDir.getName()
                      + "_" + charDir.getName(), false);
              charAllowanceChkbox
                  .setSelected(isWowCharChkboxSelected);
              if (accEnabledChkbox.isEnabled()
                  && accEnabledChkbox.isSelected()
                  && isWowCharChkboxSelected)
                wowCharacters.add(wowChar);

              charAllowanceChkbox
                  .addItemListener(new ItemListener() {

                    @Override
                    public void itemStateChanged(
                        ItemEvent arg0) {
                      boolean newStateIsSelected = arg0
                          .getStateChange() == ItemEvent.SELECTED;
                      cfg.putBoolean(
                          "CharacterAllowance_"
                              + serverDir
                                  .getName()
                              + "_"
                              + charDir.getName(),
                          newStateIsSelected);
                      if (newStateIsSelected)
                        wowCharacters.add(wowChar);
                      else
                        wowCharacters.remove(wowChar);
                    }
                  });

              ++accCharsPnl_c.gridy;
              accCharsPnl_c.insets = new Insets(0, 20, 0, 0);
              accCharsPnl.add(charAllowanceChkbox, accCharsPnl_c);
            }
          }

          if ((accCharsPnl.getComponentCount() - 1) == 0) {
            ++accCharsPnl_c.gridy;
            accCharsPnl_c.fill = GridBagConstraints.NONE; // Will
                                    // center
                                    // text.
            accCharsPnl_c.insets = new Insets(0, 5, 3, 5);
            accCharsPnl.add(new JLabel(
                S.NO_CHARACTERS_MET_REQUIREMENTS),
                accCharsPnl_c);
            accEnabledChkbox.setEnabled(false);
            accEnabledChkbox.setToolTipText(String.format(
                "<html><p>%s.%s%s.</p></html>",
                S.NO_CHARACTERS_MET_REQUIREMENTS_FOR_SYNC,
                S.HTML_NL, S.THIS_ACCOUNT_WOULDNT_BE_SYNCED));
            accCharsPnl_c.insets = null;
            accCharsPnl.setEnabled(false);
          }

          accsChckBoxesPnl.add(accCharsPnl, accsChckBoxesPnl_c);
          if (++accsChckBoxesPnl_c.gridx == 2) {
            accsChckBoxesPnl_c.gridx = 0;
            ++accsChckBoxesPnl_c.gridy;
          }
        }
      } catch (SecurityException e) {
        JOptionPane.showMessageDialog(null,
            S.EXCEPTION_SecurityException + ".");
        return accsChckBoxesPnl;
      }

      c.gridy = 1;
      wowCharsSelPnl.add(accsChckBoxesPnl, c);

      // Buttons panel for Accounts selection (e.g. Refresh available
      // accounts, start Sync, etc..)
      JPanel wowCharsActionsPnl = new JPanel(new FlowLayout(
          FlowLayout.CENTER, 10, 2));

      // Refresh available accounts of the chosen World of Warcraft
      // directory
      JButton refreshAvailCharsBttn = new JButton(
          S.REFRESH_AVAIL_ACCOUNTS);
      refreshAvailCharsBttn.addActionListener(new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent arg0) {
          updatePanels();
        }
      });
      wowCharsActionsPnl.add(refreshAvailCharsBttn);

      // Start sync
      final JButton startSyncBttn = new JButton(S.SYNC_NOW + "!");
      startSyncBttn.setFont(((Font) UIManager.getDefaults().get(
          "Button.font")).deriveFont(Font.BOLD));
      startSyncBttn.addActionListener(new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent arg0) {
          // Disable button until synchronization is completed.
          startSyncBttn.setEnabled(false);
          if (!startSync())
            JOptionPane.showMessageDialog(
                null,
                String.format(
                    "<html>%s</html>",
                    S.SYNC_UNSUCCESSFUL
                        .replace("unsuccessful",
                            "<strong style='color: red;'>unsuccessful!</strong>")
                        + S.HTML_NL
                        + S.CHECK_INTERNET_CONNECTION
                        + "."
                        + S.HTML_NL
                        + S.CHECK_IF_CHARS_ARE_SELECTED
                        + "."));
          startSyncBttn.setEnabled(true);
        }
      });
      wowCharsActionsPnl.add(startSyncBttn);

      ++c.gridy;
      c.insets = new Insets(JSKY_DEFAULT_PADDING, JSKY_DEFAULT_PADDING,
          JSKY_DEFAULT_PADDING, JSKY_DEFAULT_PADDING);
      wowCharsSelPnl.add(wowCharsActionsPnl, c);
    } else
      wowCharsSelPnl.setEnabled(false);

    return wowCharsSelPnl;
  }

  protected static void updateButtons() {
    // If no one character was selected for synchronization, disable
    // "Sync Now!" button.
    // TODO: this method maybe will not be needed at all..
  }

  public static void buildWowCharacters() {
    //
  }

  /**
   * Method which actually do synchronization. This function is invoked upon
   * "Start Sync!" button click.
   *
   * @return true on successful synchronization, false otherwise.
   * */
  static boolean startSync() {
    // If characters array is empty, it is not necessary to sync at all.
    if (wowCharacters.size() == 0)
      return false;

    for (WowCharacter wowChar : wowCharacters) {
      try {
        // Update bags information URI query creation.

        String urlParameters = "javaBankerkaBagsVersion="
            + URLEncoder.encode(
                String.valueOf(APPLICATION_VERSION), "UTF-8")
            + "&action="
            + URLEncoder.encode(WEB_ACTION_UPDATE, "UTF-8")
            + "&jsondata="
            + URLEncoder.encode(
                wowChar.getPlainBankerkaJSONString(), "UTF-8");

        dout(TARGET_HOST_URL + "?" + urlParameters);

        // HTTP POST request
        String response = excutePost(TARGET_HOST_URL, urlParameters);

        // dout(response);

        JList<String> respList = new JList<String>(
            new String[] { "<html>"
                + response.replaceAll("\n", "<br>") + "</html>" });
        JScrollPane respPane = new JScrollPane(respList);
        respPane.setPreferredSize(new Dimension(600, 400));

        JOptionPane.showMessageDialog(null, respPane,
            "Server response", JOptionPane.PLAIN_MESSAGE);
      } catch (IOException e) {
        e.printStackTrace();
      }
    }

    return true;
  }

  /**
   * Refreshes panels of World of WarCraft characters selection (called upon
   * program start and wow/launcher.exe file selection) TODO: Rewrite whole
   * method to be able refresh only one element/component at a time.
   */
  static void updatePanels() {
    mainWindowFrm.getContentPane().removeAll();
    SpringLayout layout = new SpringLayout();
    mainWindowFrm.setLayout(layout);

    // create new panels
    Component c1 = mainWindowFrm.getContentPane().add(
        createPanel_wowExeLocChoose());
    Component c2 = mainWindowFrm.getContentPane().add(
        createPanel_wowCharactersSelection());

    // Main window padding (constraints instead of one additional JPanel
    // padding..)
    layout.putConstraint(SpringLayout.NORTH, c1, JSKY_DEFAULT_PADDING,
        SpringLayout.NORTH, mainWindowFrm);
    layout.putConstraint(SpringLayout.WEST, c1, JSKY_DEFAULT_PADDING,
        SpringLayout.WEST, mainWindowFrm);

    layout.putConstraint(SpringLayout.NORTH, c2, 0, SpringLayout.SOUTH, c1);
    layout.putConstraint(SpringLayout.EAST, c2, 0, SpringLayout.EAST, c1);
    layout.putConstraint(SpringLayout.WEST, c2, 0, SpringLayout.WEST, c1);

    // dout("Components count: " +
    // mainWindowFrm.getContentPane().getComponentCount(), true);

    mainWindowFrm.revalidate();
    mainWindowFrm.repaint();

    mainWindowFrm.setMinimumSize(new Dimension(PREFFERED_WIDTH,
        PREFFERED_HEIGHT));
    mainWindowFrm.addComponentListener(new ComponentAdapter() {
      @Override
      public void componentResized(ComponentEvent e) {
        mainWindowFrm.setSize(new Dimension(PREFFERED_WIDTH,
            mainWindowFrm.getHeight()));
        super.componentResized(e);
      }
    });
    mainWindowFrm.setVisible(true);
  }

  static void dout(String txt, boolean nl) {
    if (nl == true)
      System.out.println(txt);
    else
      System.out.printf("%s", txt);
  }

  static void dout(Integer number, boolean nl) {
    dout(number.toString(), nl);
  }

  static void dout(Object obj, boolean nl) {
    dout(obj.toString(), nl);
  }

  static void dout(Object obj) {
    dout(obj != null ? obj.toString() : "dout: " + null, true);
  }

  public static String excutePost(String targetURL, String urlParameters) {
    URL url;
    HttpURLConnection connection = null;
    try {
      // Create connection
      url = new URL(targetURL);
      connection = (HttpURLConnection) url.openConnection();
      connection.setRequestMethod("POST");
      connection.setRequestProperty("Content-Type",
          "application/x-www-form-urlencoded");

      connection.setRequestProperty("Content-Length",
          "" + Integer.toString(urlParameters.getBytes().length));
      connection.setRequestProperty("Content-Language", "en-US");

      connection.setUseCaches(false);
      connection.setDoInput(true);
      connection.setDoOutput(true);

      // Send request
      DataOutputStream wr = new DataOutputStream(
          connection.getOutputStream());
      wr.writeBytes(urlParameters);
      wr.flush();
      wr.close();

      // Get Response
      InputStream is = connection.getInputStream();
      BufferedReader rd = new BufferedReader(new InputStreamReader(is));
      String line;
      StringBuffer response = new StringBuffer();
      while ((line = rd.readLine()) != null) {
        response.append(line);
        response.append('\r');
      }
      rd.close();
      return response.toString();

    } catch (Exception e) {

      e.printStackTrace();
      return null;

    } finally {

      if (connection != null) {
        connection.disconnect();
      }
    }
  }
}
TOP

Related Classes of Main

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.