/** * Creates a new {@link PlayerStatsChartFactory}. * * @param chartsComp reference to the charts component that created us */ public PlayerStatsChartFactory(final ChartsComp chartsComp) { super(chartsComp); statComboBox.addActionListener(chartsComp.chartsRebuilder); statComboBox.addActionListener( new ActionAdapter(true) { @Override public void actionPerformed(final ActionEvent event) { final boolean hasMinGas = statComboBox.getSelectedItem().hasMinGas; minsCheckBox.setVisible(hasMinGas); gasCheckBox.setVisible(hasMinGas); separateMinsGasCheckBox.setVisible(hasMinGas); } }); statComboBox.markSeparatedItems( Stat.FOOD_MADE_USED, Stat.ARMY_RES_IN_PROGRESS, Stat.ECON_RES_IN_PROGRESS); statComboBox.setMaximumRowCount(statComboBox.getItemCount()); presentationComboBox.addActionListener(chartsComp.chartsReconfigurer); minsCheckBox.setText("Minerals"); minsCheckBox.setToolTipText(Settings.PLAYER_STATS_INCLUDE_MINS.name); minsCheckBox.addActionListener(chartsComp.chartsRebuilder); gasCheckBox.setText("Gas"); gasCheckBox.setToolTipText(Settings.PLAYER_STATS_INCLUDE_GAS.name); gasCheckBox.addActionListener(chartsComp.chartsRebuilder); separateMinsGasCheckBox.setText("Separate Mins/Gas"); separateMinsGasCheckBox.setToolTipText(Settings.PLAYER_STATS_SEPARATE_MINS_GAS.name); separateMinsGasCheckBox.addActionListener(chartsComp.chartsRebuilder); }
/** * Creates a new {@link BinaryDataComp}. * * @param repProc replay processor */ public BinaryDataComp(final RepProcessor repProc) { super(repProc); hexLineSizeComboBox = SettingsGui.createSettingComboBox( Settings.HEX_LINE_SIZE, Env.APP_SETTINGS, rebuilderListener); final Vector<DataSource> sourceVector = new Vector<>(); final List<DataSource> separatedDsList = new ArrayList<>(); // The replay file sourceVector.add(new FullFileDataSource("Replay File", repProc.file)); separatedDsList.add(sourceVector.get(sourceVector.size() - 1)); // General Replay MPQ content sourceVector.add(new MpqUserDataDataSource(repProc.file)); for (final MpqContent mpqContent : MpqContent.VALUES) sourceVector.add(new MpqContentDataSource(repProc.file, mpqContent)); separatedDsList.add(sourceVector.get(sourceVector.size() - 1)); // Replay content for (final RepContent mpqContent : RepContent.VALUES) { sourceVector.add(new MpqContentDataSource(repProc.file, mpqContent)); if (mpqContent == RepContent.TRACKER_EVENTS) separatedDsList.add(sourceVector.get(sourceVector.size() - 1)); } separatedDsList.add(sourceVector.get(sourceVector.size() - 1)); // General Map MPQ content final Path mapFile = MapParser.getMapFile(repProc); sourceVector.add(new MpqUserDataDataSource(mapFile)); for (final MpqContent mpqContent : MpqContent.VALUES) sourceVector.add(new MpqContentDataSource(mapFile, mpqContent)); separatedDsList.add(sourceVector.get(sourceVector.size() - 1)); // Map content for (final MapContent mpqContent : MapContent.VALUES) sourceVector.add(new MpqContentDataSource(mapFile, mpqContent)); dataSourceComboBox = new XComboBox<>(sourceVector); dataSourceComboBox.markSeparatedItems(separatedDsList); searcher = new ByteIntPosBaseSearcher() { /** Bytes of the search text, as <code>int</code>s. */ private int[] searchTextBytes; @Override protected void prepareNew() { // Note: Texts found in binary data are usually UTF-8 encoded. // This text search converts the searched text to bytes using the same // encoding (UTF-8), and this byte sequence will be searched. // For more details see the Tips.BINARY_DATA_TEXT_SEARCH tip. final byte[] bytes = searchText.getBytes(Env.UTF8); searchTextBytes = new int[bytes.length]; maxOffset = searchTextBytes.length - 1; for (int i = maxOffset; i >= 0; i--) searchTextBytes[i] = bytes[i] & 0xff; super.prepareNew(); } @Override public boolean matches() { // Local vars for fast access final byte[] data = BinaryDataComp.this.data; final int[] searchTextBytes = this.searchTextBytes; final int searchPos = this.searchPos; if (searchPos + maxOffset > maxPos) return false; // Would overflow in data, surely cannot match for (int offset = maxOffset; offset >= 0; offset--) { final int searchChar = searchTextBytes[offset]; final int ch = data[searchPos + offset] & 0xff; if (ch != searchChar) { // Also check in a case insensitive manner (lower-cased version of ch): if (ch >= 'A' && ch <= 'Z') { if (ch - ('A' - 'a') != searchChar) return false; } else return false; } } // Match! handleMatch(); // Clear the other searcher (so it will start from this line) hexSearcher.clearLastSearchPos(); return true; } }; hexSearcher = new ByteIntPosBaseSearcher() { /** Bytes specified by the hex search text. */ private byte[] searchTextBytes; @Override protected void prepareNew() { searchTextBytes = Utils.hexToBytes(searchText); if (searchTextBytes == null) searchTextBytes = new byte[0]; maxOffset = searchTextBytes.length - 1; super.prepareNew(); } @Override public boolean matches() { if (searchTextBytes.length == 0) return true; // To end the search // Local vars for fast access final byte[] data = BinaryDataComp.this.data; final byte[] searchTextBytes = this.searchTextBytes; final int searchPos = this.searchPos; if (searchPos + maxOffset > maxPos) return false; // Would overflow in data, surely cannot match for (int offset = maxOffset; offset >= 0; offset--) if (searchTextBytes[offset] != data[searchPos + offset]) return false; // Match! handleMatch(); // Clear the other searcher (so it will start from this line) searcher.clearLastSearchPos(); return true; } }; buildGui(); }