|
35 | 35 | import android.text.method.TextKeyListener; |
36 | 36 | import android.view.ContextMenu; |
37 | 37 | import android.view.KeyEvent; |
| 38 | +import android.view.LayoutInflater; |
38 | 39 | import android.view.Menu; |
39 | 40 | import android.view.MenuItem; |
40 | 41 | import android.view.View; |
|
43 | 44 | import android.widget.Button; |
44 | 45 | import android.widget.EditText; |
45 | 46 | import android.widget.LinearLayout; |
| 47 | +import android.widget.TextView; |
46 | 48 | import android.widget.Toast; |
47 | 49 |
|
48 | 50 | import androidx.activity.result.ActivityResult; |
|
98 | 100 | import org.exbin.bined.editor.android.search.SearchParameters; |
99 | 101 | import org.exbin.bined.highlight.android.NonAsciiCodeAreaColorAssessor; |
100 | 102 | import org.exbin.bined.highlight.android.NonprintablesCodeAreaAssessor; |
| 103 | +import org.exbin.bined.highlight.android.SearchCodeAreaColorAssessor; |
101 | 104 | import org.exbin.bined.operation.android.CodeAreaOperationCommandHandler; |
102 | 105 | import org.exbin.bined.operation.undo.BinaryDataUndoRedoChangeListener; |
103 | 106 | import org.exbin.framework.bined.BinEdCodeAreaAssessor; |
@@ -150,23 +153,29 @@ public class MainActivity extends AppCompatActivity implements FileDialog.OnFile |
150 | 153 | private final BinaryStatusHandler binaryStatus = new BinaryStatusHandler(this); |
151 | 154 | private BinarySearch binarySearch; |
152 | 155 | private SearchParameters searchParameters = null; |
| 156 | + private View searchStatusPanel; |
153 | 157 | private Runnable postSaveAsAction = null; |
154 | 158 | private boolean keyboardShown = false; |
155 | 159 | private boolean dataInspectorShown = true; |
156 | 160 | private long lastBackKeyPressTime = -1; |
157 | 161 | private long lastReleaseBackKeyPressTime = -1; |
158 | | - BasicValuesPositionColorModifier basicValuesPositionColorModifier = new BasicValuesPositionColorModifier(); |
| 162 | + private BasicValuesPositionColorModifier basicValuesPositionColorModifier = new BasicValuesPositionColorModifier(); |
159 | 163 | private FallbackFileType fallbackFileType = FallbackFileType.FILE; |
160 | 164 |
|
161 | 165 | private final BinarySearchService.SearchStatusListener searchStatusListener = new BinarySearchService.SearchStatusListener() { |
162 | 166 | @Override |
163 | 167 | public void setStatus(BinarySearchService.FoundMatches foundMatches, SearchParameters.MatchMode matchMode) { |
164 | | - // TODO Add search status panel |
| 168 | + runOnUiThread(() -> { |
| 169 | + showSearchStatusPanel(); |
| 170 | + updateSearchStatusPanel(foundMatches.getMatchPosition(), foundMatches.getMatchesCount()); |
| 171 | + }); |
165 | 172 | } |
166 | 173 |
|
167 | 174 | @Override |
168 | 175 | public void clearStatus() { |
169 | | - |
| 176 | + runOnUiThread(() -> { |
| 177 | + hideSearchStatusPanel(); |
| 178 | + }); |
170 | 179 | } |
171 | 180 | }; |
172 | 181 | private final BinaryDataUndoRedoChangeListener codeAreaChangeListener = () -> { |
@@ -228,6 +237,8 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { |
228 | 237 |
|
229 | 238 | toolbar = findViewById(R.id.toolbar); |
230 | 239 | keyPanel = findViewById(R.id.keyPanel); |
| 240 | + LayoutInflater inflater = getLayoutInflater(); |
| 241 | + searchStatusPanel = inflater.inflate(R.layout.search_panel, null); |
231 | 242 | basicValuesInspectorView = findViewById(R.id.basic_values_inspector); |
232 | 243 | setSupportActionBar(toolbar); |
233 | 244 |
|
@@ -298,7 +309,12 @@ private void setupKeyPanel(KeysPanelMode keysPanelMode) { |
298 | 309 | } |
299 | 310 |
|
300 | 311 | if (keyPanelIndex == -1) { |
301 | | - mainView.addView(keyPanel, 2); |
| 312 | + int searchStatusPanelIndex = mainView.indexOfChild(searchStatusPanel); |
| 313 | + if (searchStatusPanelIndex >= 0) { |
| 314 | + mainView.addView(keyPanel, 2); |
| 315 | + } else { |
| 316 | + mainView.addView(keyPanel, searchStatusPanelIndex + 1); |
| 317 | + } |
302 | 318 | mainView.requestLayout(); |
303 | 319 | } |
304 | 320 |
|
@@ -402,6 +418,48 @@ private void setupKeyPanelSize(int buttonWidth, int buttonHeight) { |
402 | 418 | buttonTab.setMinHeight(buttonHeight); |
403 | 419 | } |
404 | 420 |
|
| 421 | + private void showSearchStatusPanel() { |
| 422 | + LinearLayout mainView = findViewById(R.id.main); |
| 423 | + int searchStatusPanelIndex = mainView.indexOfChild(searchStatusPanel); |
| 424 | + if (searchStatusPanelIndex == -1) { |
| 425 | + TextView searchStatus = searchStatusPanel.findViewById(R.id.searchStatus); |
| 426 | + Button prevButton = searchStatusPanel.findViewById(R.id.previousMatchButton); |
| 427 | + prevButton.setEnabled(false); |
| 428 | + Button nextButton = searchStatusPanel.findViewById(R.id.nextMatchButton); |
| 429 | + nextButton.setEnabled(false); |
| 430 | + |
| 431 | + Resources resources = getResources(); |
| 432 | + searchStatus.setText(resources.getString(R.string.search_in_progress)); |
| 433 | + |
| 434 | + mainView.addView(searchStatusPanel, 2); |
| 435 | + } |
| 436 | + } |
| 437 | + |
| 438 | + private void hideSearchStatusPanel() { |
| 439 | + LinearLayout mainView = findViewById(R.id.main); |
| 440 | + int searchStatusPanelIndex = mainView.indexOfChild(searchStatusPanel); |
| 441 | + if (searchStatusPanelIndex >= 0) { |
| 442 | + mainView.removeViewAt(searchStatusPanelIndex); |
| 443 | + } |
| 444 | + } |
| 445 | + |
| 446 | + private void updateSearchStatusPanel(int matchPosition, int matchesCount) { |
| 447 | + TextView searchStatus = searchStatusPanel.findViewById(R.id.searchStatus); |
| 448 | + Button prevButton = searchStatusPanel.findViewById(R.id.previousMatchButton); |
| 449 | + prevButton.setEnabled(matchPosition > 0 && matchesCount > 0); |
| 450 | + Button nextButton = searchStatusPanel.findViewById(R.id.nextMatchButton); |
| 451 | + nextButton.setEnabled(matchPosition < matchesCount - 1 && matchesCount > 0); |
| 452 | + |
| 453 | + Resources resources = getResources(); |
| 454 | + if (matchesCount == 1) { |
| 455 | + searchStatus.setText(resources.getString(R.string.search_match_single)); |
| 456 | + } else if (matchesCount > 0) { |
| 457 | + searchStatus.setText(String.format(resources.getString(R.string.search_match_found), matchPosition + 1, matchesCount)); |
| 458 | + } else { |
| 459 | + searchStatus.setText(resources.getString(R.string.search_match_none)); |
| 460 | + } |
| 461 | + } |
| 462 | + |
405 | 463 | @Override |
406 | 464 | protected void onDestroy() { |
407 | 465 | super.onDestroy(); |
@@ -568,6 +626,7 @@ public boolean onContextItemSelected(MenuItem item) { |
568 | 626 | switch (item.getItemId()) { |
569 | 627 | case GO_TO_SIDE_PANEL_POPUP_ID: { |
570 | 628 | LinearLayout mainView = findViewById(R.id.main); |
| 629 | + int searchStatusPanelIndex = mainView.indexOfChild(searchStatusPanel); |
571 | 630 | int keyPanelIndex = mainView.indexOfChild(keyPanel); |
572 | 631 | if (keyPanelIndex >= 0) { |
573 | 632 | View downButton = findViewById(R.id.buttonDown); |
@@ -875,8 +934,12 @@ public boolean onOptionsItemSelected(MenuItem item) { |
875 | 934 | searchDialog.setBinarySearch(binarySearch); |
876 | 935 | searchDialog.setSearchParameters(searchParameters); |
877 | 936 | searchDialog.setTemplateCodeArea(codeArea); |
| 937 | + searchDialog.setSearchStatusListener(searchStatusListener); |
878 | 938 | searchDialog.setOnCloseListener(() -> { |
879 | | - searchParameters = searchDialog.getSearchParameters(); |
| 939 | + SearchParameters usedSearchParameters = searchDialog.getSearchParameters(); |
| 940 | + if (usedSearchParameters != null) { |
| 941 | + searchParameters = usedSearchParameters; |
| 942 | + } |
880 | 943 | }); |
881 | 944 | searchDialog.show(getSupportFragmentManager(), "searchDialog"); |
882 | 945 | return true; |
@@ -1389,6 +1452,24 @@ public void buttonActionTab(View view) { |
1389 | 1452 | codeArea.getCommandHandler().keyPressed(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_TAB)); |
1390 | 1453 | } |
1391 | 1454 |
|
| 1455 | + public void buttonActionPreviousMatch(View view) { |
| 1456 | + SearchCodeAreaColorAssessor searchAssessor = CodeAreaAndroidUtils.findColorAssessor((ColorAssessorPainterCapable) codeArea.getPainter(), SearchCodeAreaColorAssessor.class); |
| 1457 | + searchAssessor.setCurrentMatchIndex(searchAssessor.getCurrentMatchIndex() - 1); |
| 1458 | + updateSearchStatusPanel(searchAssessor.getCurrentMatchIndex(), searchAssessor.getMatches().size()); |
| 1459 | + } |
| 1460 | + |
| 1461 | + public void buttonActionNextMatch(View view) { |
| 1462 | + SearchCodeAreaColorAssessor searchAssessor = CodeAreaAndroidUtils.findColorAssessor((ColorAssessorPainterCapable) codeArea.getPainter(), SearchCodeAreaColorAssessor.class); |
| 1463 | + searchAssessor.setCurrentMatchIndex(searchAssessor.getCurrentMatchIndex() + 1); |
| 1464 | + updateSearchStatusPanel(searchAssessor.getCurrentMatchIndex(), searchAssessor.getMatches().size()); |
| 1465 | + } |
| 1466 | + |
| 1467 | + public void buttonActionHideSearchPanel(View view) { |
| 1468 | + binarySearch.cancelSearch(); |
| 1469 | + binarySearch.clearSearch(); |
| 1470 | + hideSearchStatusPanel(); |
| 1471 | + } |
| 1472 | + |
1392 | 1473 | public static boolean isGoogleTV(Context context) { |
1393 | 1474 | final PackageManager pm = context.getPackageManager(); |
1394 | 1475 | return pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK); |
|
0 commit comments