Skip to content

Commit 76bd653

Browse files
committed
Merge remote-tracking branch 'origin/GT-0-dragonmacher-test-fixes'
2 parents e65ccd9 + e3eeb3d commit 76bd653

File tree

15 files changed

+212
-30
lines changed

15 files changed

+212
-30
lines changed

Ghidra/Features/Base/src/main/help/help/topics/ConsolePlugin/console.html

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,5 @@ <H2 align="left">Navigation</H2>
5353

5454
<P align="left" class="providedbyplugin">Provided by: <I>ConsolePlugin</I></P>
5555

56-
<P class="relatedtopic">Related Topics:</P>
5756
</BODY>
5857
</HTML>

Ghidra/Features/Base/src/test.slow/java/docking/widgets/table/GTableTest.java

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*/
1616
package docking.widgets.table;
1717

18-
import static org.junit.Assert.assertEquals;
18+
import static org.junit.Assert.*;
1919

2020
import java.awt.BorderLayout;
2121

@@ -36,7 +36,6 @@ public class GTableTest extends AbstractGhidraHeadedIntegrationTest {
3636
public void setUp() throws Exception {
3737
model = new TestDataModel();
3838
table = new GhidraTable(model);
39-
table.setAutoLookupColumn(4);
4039

4140
frame = new JFrame("Ghidra Table Test");
4241
frame.getContentPane().setLayout(new BorderLayout());
@@ -52,6 +51,9 @@ public void tearDown() throws Exception {
5251

5352
@Test
5453
public void testAutoLookup() throws Exception {
54+
55+
table.setAutoLookupColumn(4);
56+
5557
setSelectedRow(table, 0);
5658

5759
triggerText(table, "a");
@@ -72,6 +74,44 @@ public void testAutoLookup() throws Exception {
7274
assertEquals(11, table.getSelectedRow());
7375
}
7476

77+
@Test
78+
public void testSetActionsEnabled() throws Exception {
79+
80+
table.setAutoLookupColumn(4);
81+
assertFalse(table.areActionsEnabled());
82+
setSelectedRow(table, 0);
83+
84+
triggerText(table, "a");
85+
assertEquals("Auto-lookup failed to change the table row", 11, table.getSelectedRow());
86+
87+
// this will disable 'auto lookup'
88+
table.setActionsEnabled(true);
89+
setSelectedRow(table, 0);
90+
91+
triggerText(table, "a");
92+
assertEquals("Auto-lookup should be disabled when actions are enabled", 0,
93+
table.getSelectedRow());
94+
95+
table.setActionsEnabled(false);
96+
setSelectedRow(table, 0);
97+
98+
triggerText(table, "a");
99+
assertEquals("Auto-lookup failed to change the table row", 11, table.getSelectedRow());
100+
101+
table.setActionsEnabled(true);
102+
setSelectedRow(table, 0);
103+
104+
triggerText(table, "a");
105+
assertEquals("Auto-lookup should be disabled when actions are enabled", 0,
106+
table.getSelectedRow());
107+
108+
table.setAutoLookupColumn(4);
109+
setSelectedRow(table, 0);
110+
111+
triggerText(table, "a");
112+
assertEquals("Auto-lookup failed to change the table row", 11, table.getSelectedRow());
113+
}
114+
75115
private void timeout() throws InterruptedException {
76116
Thread.sleep(GTable.KEY_TIMEOUT * 2);
77117
}

Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/codebrowser/AbstractCodeBrowserNavigationTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public void setUp() throws Exception {
5959
addrFactory = program.getAddressFactory();
6060

6161
NextPrevAddressPlugin np = env.getPlugin(NextPrevAddressPlugin.class);
62-
prev = getAction(np, "Previous in History Buffer");
62+
prev = getAction(np, "Previous Location in History");
6363
clearHistory = getAction(np, "Clear History Buffer");
6464
cb = env.getPlugin(CodeBrowserPlugin.class);
6565

Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/codebrowser/CodeBrowserNavigationSegmentedAddressTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ public void setUp() throws Exception {
6565
tool.addPlugin(LocationReferencesPlugin.class.getName());
6666
tool.addPlugin(MarkerManagerPlugin.class.getName());
6767
NextPrevAddressPlugin np = env.getPlugin(NextPrevAddressPlugin.class);
68-
prev = getAction(np, "Previous in History Buffer");
68+
prev = getAction(np, "Previous Location in History");
6969
clearHistory = getAction(np, "Clear History Buffer");
7070
cb = env.getPlugin(CodeBrowserPlugin.class);
7171
nextFunction = getAction(cb, "Go to next function");

Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/codebrowser/CodeBrowserOptionsTest.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,6 @@ public void testOptionsHeaders() throws Exception {
184184
assertEquals("Cursor", groups[idx++]);
185185
assertEquals("Cursor Text Highlight", groups[idx++]);
186186
assertEquals("EOL Comments Field", groups[idx++]);
187-
assertEquals("Field Name", groups[idx++]);
188187
assertEquals("Format Code", groups[idx++]);
189188
assertEquals("Function Pointers", groups[idx++]);
190189
assertEquals("Function Signature Field", groups[idx++]);
@@ -193,9 +192,9 @@ public void testOptionsHeaders() throws Exception {
193192
assertEquals("Mouse", groups[idx++]);
194193
assertEquals("Operands Field", groups[idx++]);
195194
assertEquals("Pcode Field", groups[idx++]);
196-
assertEquals("Plate Comment", groups[idx++]);
197-
assertEquals("Post Comment", groups[idx++]);
198-
assertEquals("Pre-Comment", groups[idx++]);
195+
assertEquals("Plate Comments Field", groups[idx++]);
196+
assertEquals("Post-comments Field", groups[idx++]);
197+
assertEquals("Pre-comments Field", groups[idx++]);
199198
assertEquals("Register Field", groups[idx++]);
200199
assertEquals("Selection Colors", groups[idx++]);
201200
assertEquals("XREFs Field", groups[idx++]);

Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/codebrowser/CodeBrowserTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ public void setUp() throws Exception {
7676
pm.openProgram(program.getDomainFile());
7777

7878
NextPrevAddressPlugin np = env.getPlugin(NextPrevAddressPlugin.class);
79-
getAction(np, "Previous in History Buffer");
79+
getAction(np, "Previous Location in History");
8080
getAction(np, "Clear History Buffer");
8181
cb = env.getPlugin(CodeBrowserPlugin.class);
8282
fp = cb.getFieldPanel();

Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/navigation/GoToPluginTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -603,8 +603,8 @@ public void testQueryResultsDialogNavigation() throws Exception {
603603
public void testNextPrevious() throws Exception {
604604
tool.addPlugin(NextPrevAddressPlugin.class.getName());
605605
NextPrevAddressPlugin np = env.getPlugin(NextPrevAddressPlugin.class);
606-
DockingActionIf next = getAction(np, "Next in History Buffer");
607-
DockingActionIf prev = getAction(np, "Previous in History Buffer");
606+
DockingActionIf next = getAction(np, "Next Location in History");
607+
DockingActionIf prev = getAction(np, "Previous Location in History");
608608
DockingActionIf clear = getAction(np, "Clear History Buffer");
609609
assertTrue(!clear.isEnabledForContext(provider.getActionContext(null)));
610610
assertTrue(!next.isEnabledForContext(provider.getActionContext(null)));
@@ -765,7 +765,7 @@ public void testNavigateToOtherProgramOption() throws Exception {
765765
setOptionToAllowNavigationToOtherOpenPrograms();
766766
performOkCallback();
767767

768-
assertTrue("Expected goto to succeed and dialog to be gone", !dialog.isShowing());
768+
assertFalse("Expected goto to succeed and dialog to be gone", dialog.isShowing());
769769

770770
}
771771

Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/navigation/NavigationHistoryPluginTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,8 @@ public void setUp() throws Exception {
7575
cb = env.getPlugin(CodeBrowserPlugin.class);
7676
goToService = tool.getService(GoToService.class);
7777
navigatable = goToService.getDefaultNavigatable();
78-
prevAction = getAction(nextPrevPlugin, "Previous in History Buffer");
79-
nextAction = getAction(nextPrevPlugin, "Next in History Buffer");
78+
prevAction = getAction(nextPrevPlugin, "Previous Location in History");
79+
nextAction = getAction(nextPrevPlugin, "Next Location in History");
8080
ProgramManagerPlugin pmp = env.getPlugin(ProgramManagerPlugin.class);
8181
undoAction = getAction(pmp, "Undo");
8282
redoAction = getAction(pmp, "Redo");

Ghidra/Features/FunctionGraph/src/test/java/ghidra/app/plugin/core/functiongraph/AbstractFunctionGraphTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2291,7 +2291,7 @@ protected void moveView(int amount) {
22912291
}
22922292

22932293
protected void navigateBack() {
2294-
String name = "Previous in History Buffer";
2294+
String name = "Previous Location in History";
22952295

22962296
DockingActionIf action = getAction(tool, "NextPrevAddressPlugin", name);
22972297
performAction(action, true);

Ghidra/Features/Python/src/main/help/help/topics/Python/interpreter.html

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,5 @@ <H2>Additional Help</H2>
165165

166166
<P align="left" class="providedbyplugin">Provided by: <I>PythonPlugin</I></P>
167167

168-
<P class="relatedtopic">Related Topics:</P>
169168
</BODY>
170169
</HTML>

Ghidra/Framework/Docking/src/main/java/docking/actions/KeyBindingUtils.java

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -176,8 +176,14 @@ public static void exportKeyBindings(ToolOptions keyBindingOptions) {
176176
/**
177177
* Changes the given key event to the new source component and then dispatches that event.
178178
* This method is intended for clients that wish to effectively take a key event given to
179-
* one component and give it to another component. This is seldom-used code; if you don't
180-
* know when to use this code, then don't.
179+
* one component and give it to another component.
180+
*
181+
* <p>This method exists to deal with the complicated nature of key event processing and
182+
* how our (not Java's) framework processes key event bindings to trigger actions. If not
183+
* for our special processing of action key bindings, then this method would not be
184+
* necessary.
185+
*
186+
* <p><b>This is seldom-used code; if you don't know when to use this code, then don't.</b>
181187
*
182188
* @param newSource the new target of the event
183189
* @param e the existing event
@@ -190,9 +196,44 @@ public static void retargetEvent(Component newSource, KeyEvent e) {
190196

191197
KeyEvent newEvent = new KeyEvent(newSource, e.getID(), e.getWhen(), e.getModifiersEx(),
192198
e.getKeyCode(), e.getKeyChar(), e.getKeyLocation());
193-
e.consume();
199+
200+
/*
201+
Unusual Code Alert!
202+
203+
The KeyboardFocusManager is a complicated beast. Here we use knowledge of one such
204+
complication to correctly route key events. If the client of this method passes
205+
a component whose 'isShowing()' returns false, then the manager will not send the
206+
event to that component. Almost all clients will pass fully attached/realized
207+
components to the manager. We, however, will sometimes pass components that are not
208+
attached; for example, when we are using said components with a renderer to perform
209+
our own painting. In the case of non-attached components, we must call the
210+
redispatchEvent() method ourselves.
211+
212+
Why don't we just always call redispatchEvent()? Well, that
213+
method will not pass the new cloned event we just created back through the full
214+
key event pipeline. This means that tool-level (our Tool API, not Java)
215+
actions will not work, as tool-level actions are handled at the beginning of the
216+
key event pipeline, not by the components themselves.
217+
218+
Also, we have here guilty knowledge that the aforementioned tool-level key processing
219+
will check to see if the event was consumed. If consumed, then no further processing
220+
will happen; if not consumed, then the framework will continue to process the event
221+
passed into this method. Thus, after we send the new event, we will update the
222+
original event to match the consumed state of our new event. This means that the
223+
component passed to this method must, somewhere in its processing, consume the key
224+
event we dispatch here, if they do not wish for any further processing to take place.
225+
*/
194226
KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
195-
kfm.dispatchEvent(newEvent);
227+
if (newSource.isShowing()) {
228+
kfm.dispatchEvent(newEvent);
229+
}
230+
else {
231+
kfm.redispatchEvent(newSource, newEvent);
232+
}
233+
234+
if (newEvent.isConsumed()) {
235+
e.consume();
236+
}
196237
}
197238

198239
/**

Ghidra/Framework/Docking/src/main/java/docking/widgets/table/GTable.java

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ public class GTable extends JTable {
8484
private int userDefinedRowHeight;
8585

8686
private boolean isInitialized;
87-
private boolean allowActions;
87+
private boolean enableActionKeyBindings;
8888
private KeyListener autoLookupListener;
8989
private long lastLookupTime;
9090
private String lookupString;
@@ -386,6 +386,11 @@ else if (compare > 0) {
386386

387387
/**
388388
* Sets the column in which auto-lookup will be enabled.
389+
*
390+
* <p>Note: calling this method with a valid column index will disable key binding support
391+
* of actions. See {@link #setActionsEnabled(boolean)}. Passing an invalid column index
392+
* will disable the auto-lookup feature.
393+
*
389394
* @param lookupColumn the column in which auto-lookup will be enabled
390395
*/
391396
public void setAutoLookupColumn(int lookupColumn) {
@@ -395,7 +400,8 @@ public void setAutoLookupColumn(int lookupColumn) {
395400
autoLookupListener = new KeyAdapter() {
396401
@Override
397402
public void keyPressed(KeyEvent e) {
398-
if (!allowActions) {
403+
if (enableActionKeyBindings) {
404+
// actions will consume key bindings, so don't process them
399405
return;
400406
}
401407

@@ -428,6 +434,7 @@ public void keyPressed(KeyEvent e) {
428434

429435
if (lookupColumn >= 0 && lookupColumn < getModel().getColumnCount()) {
430436
addKeyListener(autoLookupListener);
437+
enableActionKeyBindings = false;
431438
}
432439
else {
433440
removeKeyListener(autoLookupListener);
@@ -471,7 +478,22 @@ private boolean isUnmodifiedOrShift(int modifiers) {
471478
* @param b true allows keyboard actions to pass up the component hierarchy.
472479
*/
473480
public void setActionsEnabled(boolean b) {
474-
allowActions = b;
481+
enableActionKeyBindings = b;
482+
}
483+
484+
/**
485+
* Returns true if key strokes are used to trigger actions.
486+
*
487+
* <p>This method has a relationship with {@link #setAutoLookupColumn(int)}. If this method
488+
* returns <code>true</code>, then the auto-lookup feature is disabled. If this method
489+
* returns <code>false</code>, then the auto-lookup may or may not be enabled.
490+
*
491+
* @return true if key strokes are used to trigger actions
492+
* @see #setActionsEnabled(boolean)
493+
* @see #setAutoLookupColumn(int)
494+
*/
495+
public boolean areActionsEnabled() {
496+
return enableActionKeyBindings;
475497
}
476498

477499
/**

Ghidra/Framework/Generic/src/main/java/ghidra/util/DateUtils.java

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import java.time.format.DateTimeParseException;
2323
import java.time.temporal.TemporalAccessor;
2424
import java.util.*;
25+
import java.util.function.Predicate;
2526

2627
import ghidra.util.exception.AssertException;
2728

@@ -265,21 +266,69 @@ private static Date toDate(LocalDate ld) {
265266
//@formatter:on
266267
}
267268

269+
/**
270+
* Returns a date for the given numeric values
271+
*
272+
* @param year the year
273+
* @param month the month; 0-based
274+
* @param day the day of month; 1-based
275+
* @return the date
276+
*/
268277
public static Date getDate(int year, int month, int day) {
269278
Calendar cal = new GregorianCalendar(year, month, day);
270279
return cal.getTime();
271280
}
272281

282+
/**
283+
* Returns all days between the two dates. Returns 0 if the same date is passed for both
284+
* parameters. The order of the dates does not matter.
285+
*
286+
* @param date1 the first date
287+
* @param date2 the second date
288+
* @return the number of days
289+
*/
273290
public static int getDaysBetween(Date date1, Date date2) {
274-
date1 = normalizeDate(date1);
275-
date2 = normalizeDate(date2);
291+
return doGetDaysBetween(date1, date2, DateUtils::anyDay);
292+
}
293+
294+
/**
295+
* Returns the <b>business days</b> between the two dates. Returns 0 if the same date is
296+
* passed for both parameters. The order of the dates does not matter.
297+
*
298+
* @param date1 the first date
299+
* @param date2 the second date
300+
* @return the number of days
301+
*/
302+
public static int getBusinessDaysBetween(Date date1, Date date2) {
303+
return doGetDaysBetween(date1, date2, DateUtils::isBusinessDay);
304+
}
305+
306+
private static boolean anyDay(Calendar c) {
307+
return true;
308+
}
309+
310+
private static boolean isBusinessDay(Calendar c) {
311+
return !(isWeekend(c) || isHoliday(c));
312+
}
313+
314+
private static int doGetDaysBetween(Date date1, Date date2, Predicate<Calendar> dayFilter) {
315+
316+
Date d1 = date1;
317+
Date d2 = date2;
318+
if (date1.compareTo(date2) > 0) {
319+
d1 = date2;
320+
d2 = date1;
321+
}
322+
323+
d1 = normalizeDate(d1);
324+
d2 = normalizeDate(d2);
276325

277326
Calendar cal = new GregorianCalendar();
278-
cal.setTime(date1);
327+
cal.setTime(d1);
279328
int days = 0;
280-
while (cal.getTime().compareTo(date2) < 0) {
329+
while (cal.getTime().compareTo(d2) < 0) {
281330
cal.add(Calendar.DAY_OF_MONTH, 1);
282-
if (!isWeekend(cal) && !isHoliday(cal)) {
331+
if (dayFilter.test(cal)) {
283332
days++;
284333
}
285334
}

0 commit comments

Comments
 (0)