mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-06 03:50:02 +02:00
GT-2724,2216 - Table Chooser Dialog - Improvements: 1) objects instead
of row numbers are used to track work items, 2) added API methods for things like removing items, and getting a dialog closed notification; added tests
This commit is contained in:
parent
49c2010b63
commit
d474d83166
14 changed files with 670 additions and 361 deletions
|
@ -1,43 +0,0 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package generic.platform;
|
||||
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
|
||||
import org.apache.commons.lang3.reflect.MethodUtils;
|
||||
|
||||
/**
|
||||
* A general interface for handle Mac Application callbacks. Some possible callbacks are:
|
||||
* <ul>
|
||||
* <li>quit</li>
|
||||
* <li>about</li>
|
||||
* <li>preferences</li>
|
||||
* <li>file handling</li>
|
||||
* </ul>
|
||||
*
|
||||
* see com.apple.eawt.Application
|
||||
*/
|
||||
abstract class AbstractMacHandler implements InvocationHandler {
|
||||
|
||||
|
||||
|
||||
protected Object getApplication() throws Exception {
|
||||
Class<?> clazz = Class.forName("com.apple.eawt.Application");
|
||||
Object application = MethodUtils.invokeExactStaticMethod(clazz, "getApplication");
|
||||
return application;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,77 +0,0 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package generic.platform;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
|
||||
import org.apache.commons.lang3.reflect.MethodUtils;
|
||||
|
||||
import ghidra.framework.OperatingSystem;
|
||||
import ghidra.framework.Platform;
|
||||
import ghidra.util.Msg;
|
||||
|
||||
/**
|
||||
* A base implementation for creating an 'About' menu action callback. This is executed when
|
||||
* the user presses the Dock's 'Ghidra->About' menu action.
|
||||
* <p>
|
||||
* Simply constructing this class will register it.
|
||||
* <p>
|
||||
* See
|
||||
* com.apple.eawt.Application.setAboutHandler(AboutHandler)
|
||||
* com.apple.eawt.AboutHandler.handleAbout(AboutEvent)
|
||||
*/
|
||||
public abstract class MacAboutHandler extends AbstractMacHandler {
|
||||
|
||||
public MacAboutHandler() {
|
||||
addAboutApplicationListener();
|
||||
}
|
||||
|
||||
public abstract void about();
|
||||
|
||||
private void addAboutApplicationListener() {
|
||||
if (Platform.CURRENT_PLATFORM.getOperatingSystem() != OperatingSystem.MAC_OS_X) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
Object application = getApplication();
|
||||
setAboutHandler(application);
|
||||
}
|
||||
catch (Exception e) {
|
||||
Msg.error(this, "Unable to install Mac quit handler", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void setAboutHandler(Object application) throws Exception {
|
||||
|
||||
Class<?> aboutHandlerClass = Class.forName("com.apple.eawt.AboutHandler");
|
||||
Object aboutHandler = Proxy.newProxyInstance(getClass().getClassLoader(),
|
||||
new Class[] { aboutHandlerClass }, this);
|
||||
MethodUtils.invokeMethod(application, "setAboutHandler", aboutHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
|
||||
// Args: AboutEvent
|
||||
|
||||
about(); // call our about() callback, ignoring the Application API
|
||||
|
||||
// the handleAbout() is void--return null
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -1,83 +0,0 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package generic.platform;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
|
||||
import org.apache.commons.lang3.reflect.MethodUtils;
|
||||
|
||||
import ghidra.framework.OperatingSystem;
|
||||
import ghidra.framework.Platform;
|
||||
import ghidra.util.Msg;
|
||||
|
||||
/**
|
||||
* A base implementation for creating an 'Quit' menu action callback. This is executed when
|
||||
* the user presses the Dock's 'Ghidra->Quit' menu action.
|
||||
* <p>
|
||||
* Simply constructing this class will register it.
|
||||
* <p>
|
||||
* See
|
||||
* com.apple.eawt.Application.setQuitHandler(QuitHandler)
|
||||
* com.apple.eawt.AboutHandler.handleQuitRequestWith(QuitEvent, QuitResponse)
|
||||
*/
|
||||
public abstract class MacQuitHandler extends AbstractMacHandler {
|
||||
|
||||
public MacQuitHandler() {
|
||||
addQuitApplicationListener(this);
|
||||
}
|
||||
|
||||
public abstract void quit();
|
||||
|
||||
private void addQuitApplicationListener(MacQuitHandler macQuitHandler) {
|
||||
if (Platform.CURRENT_PLATFORM.getOperatingSystem() != OperatingSystem.MAC_OS_X) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
Object application = getApplication();
|
||||
setQuitHandler(application);
|
||||
}
|
||||
catch (Exception e) {
|
||||
Msg.error(this, "Unable to install Mac quit handler", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void setQuitHandler(Object application) throws Exception {
|
||||
|
||||
Class<?> quitHandlerClass = Class.forName("com.apple.eawt.QuitHandler");
|
||||
Object quitHandler = Proxy.newProxyInstance(getClass().getClassLoader(),
|
||||
new Class[] { quitHandlerClass }, this);
|
||||
MethodUtils.invokeMethod(application, "setQuitHandler", quitHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
|
||||
// Args: QuitEvent event, QuitResponse response
|
||||
|
||||
// Call QuitResponse.cancelQuit(), as we will allow our tool to quit the application
|
||||
// instead of the OS.
|
||||
Object response = args[1];
|
||||
MethodUtils.invokeExactMethod(response, "cancelQuit");
|
||||
|
||||
quit();
|
||||
|
||||
// the handleQuitRequestWith() is void--return null
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -20,12 +20,15 @@ import static org.junit.Assert.fail;
|
|||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.BooleanSupplier;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.rules.TestName;
|
||||
|
||||
import ghidra.framework.Application;
|
||||
import ghidra.framework.TestApplicationUtils;
|
||||
import ghidra.util.SystemUtilities;
|
||||
import ghidra.util.UniversalIdGenerator;
|
||||
|
@ -341,7 +344,24 @@ public abstract class AbstractGTest {
|
|||
}
|
||||
|
||||
/**
|
||||
* Waits for the given condition to return true.
|
||||
* Waits for the given latch to be counted-down
|
||||
*
|
||||
* @param latch the latch to await
|
||||
* @throws AssertionFailedError if the condition is not met within the timeout period
|
||||
*/
|
||||
public static void waitFor(CountDownLatch latch) {
|
||||
try {
|
||||
if (!latch.await(DEFAULT_WAIT_TIMEOUT, TimeUnit.MILLISECONDS)) {
|
||||
throw new AssertionFailedError("Timed-out waiting for CountDownLatch");
|
||||
}
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
fail("Interrupted waiting for CountDownLatch");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for the given condition to return true
|
||||
*
|
||||
* @param condition the condition that returns true when satisfied
|
||||
* @throws AssertionFailedError if the condition is not met within the timeout period
|
||||
|
@ -351,7 +371,7 @@ public abstract class AbstractGTest {
|
|||
}
|
||||
|
||||
/**
|
||||
* Waits for the given condition to return true.
|
||||
* Waits for the given condition to return true
|
||||
*
|
||||
* @param condition the condition that returns true when satisfied
|
||||
* @throws AssertionFailedError if the condition is not met within the timeout period
|
||||
|
@ -380,7 +400,7 @@ public abstract class AbstractGTest {
|
|||
*
|
||||
* <P>Most clients should use {@link #waitForCondition(BooleanSupplier)}.
|
||||
*
|
||||
* @param condition the condition that returns true when satisfied
|
||||
* @param supplier the supplier that returns true when satisfied
|
||||
*/
|
||||
public static void waitForConditionWithoutFailing(BooleanSupplier supplier) {
|
||||
waitForCondition(supplier, false /*failOnTimeout*/, null /*failure message*/);
|
||||
|
@ -465,7 +485,6 @@ public abstract class AbstractGTest {
|
|||
* throwing an exception if that does not happen by the given timeout.
|
||||
*
|
||||
* @param supplier the supplier of the value
|
||||
* @param timeoutMillis the timeout
|
||||
* @param failureMessage the message to print upon the timeout being reached
|
||||
* @param failOnTimeout if true, an exception will be thrown if the timeout is reached
|
||||
* @return the value
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -16,13 +15,15 @@
|
|||
*/
|
||||
package ghidra.util.datastruct;
|
||||
|
||||
/**
|
||||
* Factory for creating containers to use in various threading environments
|
||||
*/
|
||||
public class WeakDataStructureFactory {
|
||||
|
||||
/**
|
||||
* Use when all access are on a single thread, such as the Swing thread.
|
||||
*
|
||||
* @return a new WeakSet
|
||||
* @see CopyOnWriteReadWeakSet
|
||||
*/
|
||||
public static <T> WeakSet<T> createSingleThreadAccessWeakSet() {
|
||||
return new ThreadUnsafeWeakSet<T>();
|
||||
|
@ -32,7 +33,7 @@ public class WeakDataStructureFactory {
|
|||
* Use when mutations outweigh iterations.
|
||||
*
|
||||
* @return a new WeakSet
|
||||
* @see CopyOnWriteReadWeakSet
|
||||
* @see CopyOnReadWeakSet
|
||||
*/
|
||||
public static <T> WeakSet<T> createCopyOnReadWeakSet() {
|
||||
return new CopyOnReadWeakSet<T>();
|
||||
|
@ -47,5 +48,4 @@ public class WeakDataStructureFactory {
|
|||
public static <T> WeakSet<T> createCopyOnWriteWeakSet() {
|
||||
return new CopyOnWriteWeakSet<T>();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -76,17 +76,21 @@ public abstract class WeakSet<T> implements Iterable<T> {
|
|||
//==================================================================================================
|
||||
|
||||
/**
|
||||
* Add the given object to the set.
|
||||
* Add the given object to the set
|
||||
* @param t the object to add
|
||||
*/
|
||||
public abstract void add(T t);
|
||||
|
||||
/**
|
||||
* Remove the given object from the data structure
|
||||
* @param t the object to remove
|
||||
*
|
||||
*/
|
||||
public abstract void remove(T t);
|
||||
|
||||
/**
|
||||
* Returns true if the given object is in this data structure
|
||||
* @return true if the given object is in this data structure
|
||||
*/
|
||||
public abstract boolean contains(T t);
|
||||
|
||||
|
@ -97,11 +101,13 @@ public abstract class WeakSet<T> implements Iterable<T> {
|
|||
|
||||
/**
|
||||
* Return the number of objects contained within this data structure
|
||||
* @return the size
|
||||
*/
|
||||
public abstract int size();
|
||||
|
||||
/**
|
||||
* Return whether this data structure is empty.
|
||||
* Return whether this data structure is empty
|
||||
* @return whether this data structure is empty
|
||||
*/
|
||||
public abstract boolean isEmpty();
|
||||
|
||||
|
@ -119,4 +125,9 @@ public abstract class WeakSet<T> implements Iterable<T> {
|
|||
public Stream<T> stream() {
|
||||
return values().stream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return values().toString();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue