How to receive drop events in a wxTextCtrl? - drag-and-drop

I have a wxTextCtrl-derived class that overrides OnDropFiles. However, dragging something over the control does nothing. (The cursor changes to the 'not allowed' cursor.) I tried DragAcceptFiles(true) but that only enabled the built-in drop handler. (Which just loads the file into the control.) How can I get my own handler to be invoked?
I also tried SetDropTarget, but that never got invoked either. It worked in a wxFrame, though.
Any ideas?

This is a stripped down version of what I have in one of my projects:
My form code
wxTextCtrl* textctrl = new wxTextCtrl(...);
textctrl->SetDropTarget(new DropFiles(textctrl));
The dropfiles class
class DropFiles: public wxFileDropTarget{
public:
DropFiles(wxTextCtrl *text): m_Text(text){}
bool OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& arrFilenames);
private:
wxTextCtrl *m_Text;
};
bool DropFiles::OnDropFiles(wxCoord WXUNUSED(x), wxCoord WXUNUSED(y), const wxArrayString& arrFilenames){
//Just take the first filename
m_Text->SetValue(arrFilenames.Item(0));
return true;
}
Hope that helps!

You have to handle the EVT_DROP_FILES event. Any other attempt to get notified will fail :(

Related

MAUI Text Entry on Complete not Working - Possible Work around?

I'm trying to use text entry on maui to fire an event when completed. I have set the "Completed" event to a handler and it works correctly on windows. But on Android I have no joy, the event just isn't firing.
I realise there is a bug in Maui which is preventing this. But it looks like the problem was discovered in August? It's a fairly basic thing, well at least it appears to be on the face of things.
What is the best work around for this? The only thing I can think is by using the textchanged event instead of completed. This works correctly, but then i have to bodge it by doing this sort of thing:
if (entry1.Text.EndsWith("#"))
{
//Then string is complete, so need to fire correct event
System.Diagnostics.Debug.WriteLine("Complete String Detected");
}
This works and I can use it since I'm awaiting for input from a barcode scanner, so I can set the last terminating character to whatever I want. In this case I set it to a #. I can't figure out a way to detect the return key being pressed.
Thanks
Andrew
There is a similar issue on the github about the Entry.Completed and Entry.ReturnCommand not executed.
This comment shows the cause and the workaround about this problem.
detect the return key being pressed
In addition, I can't understand the problem. I have created a sample to test. The Entry.Completed event will call when I pressed the enter key. I don't kown the return key you mentioned is what. But you can use the IOnKeyListener for the android to detect any key being pressed.
Create a Listener class in the /Platform/Android:
public class MyKeyListener : Java.Lang.Object, IOnKeyListener
{
public bool OnKey(global::Android.Views.View v, [GeneratedEnum] Keycode keyCode, KeyEvent e)
{
var edittext = v as AppCompatEditText;
if (keyCode == Keycode.Enter && e.Action == KeyEventActions.Down )
//I used the Entry key as the example, you can use any other key you want to replace it.
{
edittext.ClearFocus();
edittext.SetBackgroundColor(Color.GreenYellow);
return true;
}
return false;
}
And in the page.xml:
<Entry Completed="Entry_Completed" x:Name="entry"/>
Set the listener to the entry by overriding the OnHandlerChanged() in the page.cs:
protected override void OnHandlerChanged()
      {
            base.OnHandlerChanged();
#if ANDROID
(entry.Handler.PlatformView as AndroidX.AppCompat.Widget.AppCompatEditText).SetOnKeyListener(new MauiAppTest.Platforms.Android.MyKeyListener());
#endif
}
You can also set the listener with the handler. Finally, you can try both the method above and the workaround in the issue on the github.

Wicket 6 - Feedback message not showing until request after the request in which it happened

I have an AjaxButton. The event fires, and I'm testing a scenario where I need to add a feedback and return without committing the change. I add the feedback at the page level (our feedback only shows page level messages...others are showing on component level feedback panels). I add the WebMarkupContainer that contains the feedback panel to the target. This exact thing works on every other button on the page.
But for this button, which happens to be the only one where defaultformprocessing is not false, the feedback doesn't show. To the user's view, nothing happens except our processing veil appears and then disappears. If I hit submit again, THEN the message and feedback are shown. I stuck a timestamp on it to see if it was showing the one from the 2nd request or the 1st. It's from the 1st.
What's more, a breakpoint in the feedback's filter shows that the filter was never called in the 1st request, but is called BEFORE the event processing on the 2nd request. It accepts the message as intended.
I set defaultformprocessing to FALSE on this button as a test, and in fact, messages suddenly work. But of course, that also means the form doesn't get processed. Can someone help me square this circle?
AjaxButton:
add(new AjaxButton("btnCreateRequest", getForm()) {
#Override
public void onSubmit(AjaxRequestTarget target, Form<?> form) {
//stuff happens
target.add(getFeedbackPanelForAjax());
String date = new Date().toGMTString();
System.out.println("ADDING MESSAGE - " + date);
getPage().error("This is a message! " + date);
return;
}
#Override
public void onError(AjaxRequestTarget target, Form<?> form) {
getPage().error("There was an error processing your request");
target.add(getFeedbackPanelForAjax());
target.add(form);
}
}.setVisible(enabled));
UPDATE:
getFeedbackPanelForAjax returns the web markup container that the feedback resides in. I've also tried adding the feedback directly to the target.
public Component getFeedbackPanelForAjax() {
return (Component) getForm().get("feedbackWmc");
}
Where the feedback is added:
feedback = new FRFeedbackPanel("feedback") {
#Override
public boolean isVisible() {
if(anyMessage()){
return true;
} else {
return false;
}
}
};
// feedback container
WebMarkupContainer feedbackWmc = new WebMarkupContainer("feedbackWmc");
getForm().add(feedbackWmc.setOutputMarkupId(true).setOutputMarkupPlaceholderTag(true));
feedbackWmc.add(feedback.setOutputMarkupId(true).setOutputMarkupPlaceholderTag(true));
I can say that through debugging, I put a breakpoint in anyMessage() and it returns false in this case at the same time that getPage().getFeedbackMessages() returns the message correctly. I commented out this override of isVisible() and indeed, the message shows. The problem is, that it means the artifacts of the feedback panel show when there are no messages as well, which is not what we want.
This anyMessage() solution works perfectly when I'm in an event that is defaultformprocessing=false. I suppose I could do an anyMessage() || getPage().getFeedbackMessages(), but my understanding was that anyMessage was supposed to find if there was ANY message in the hierarchy for this panel. Is that not so?
I assume you cannot replicate the problem in a small quickstart?
One idea: I've seen similar problems when the FeedbackPanel collects its messages too early, i.e. before you add the error to the page.
FeedbackMessagesModel keeps the messages to render until the end of the request - maybe some of your code triggers this by accessing the messages model.

Is it possible/how to display a message on the FeedbackPanel more than one time

I have a org.apache.wicket.markup.html.panel.FeedbackPanel in my panelA class. The feedback panel is instantiated in a panelA constructor with one message to display -> feedbackPanel.info("displayFirstTime"). I am navigating to a new page and later to the previous panelA with a command
target.getPage().get(BasePage.CONTENT_PANEL_ID).replaceWith(panelA);
but the message "displayFirstTime" won't be displayed on the feedback panel again.
I have made it with overriding a panel onBeforeRender method
#Override
public void onBeforeRender() {
super.onBeforeRender();
if (again_displayCondition) {
this.info("displayFirstTime");
}
}
but it's not a clean solution.
Is it possible or how to make it, that when moving to a panelA page for the 2nd time the feedback message will be also displayed ?
Wicket uses application.getApplicationSettings().getFeedbackMessageCleanupFilter() to delete the feedback messages at the end of the request cycle.
By default it will delete all already rendered messages.
You can setup a custom cleanup filter that may leave some of the messages, e.g. if they implement some interface. For example:
component.info(new DoNotDeleteMe("The actual message here."));
and your filter will have to check:
#Override
public boolean accept(FeedbackMessage message)
{
if (message.getMessage() instanceOf DoNotDeleteMe) {
return false;
}
return message.isRendered();
}
Make sure you implement DoNotDeleteMe#toString() so that it renders properly. Or you will have to use a custom FeedbackPanel too.
DoNotDeleteMe must implement java.io.Serializable!

MS Word VSTO Addin Find.Execute fires ContentControlOnEnter event

It seems that if Find.Execute finds a result inside a ContentControl, it will cause the ContentControlOnEnter and ContentControlOnExit events to fire. It's particularly annoying because the exit event fires even if the selection is still in the content control, so any code which sets the states of buttons dependent upon a content control being active will appear to be in the incorrect state.
Given a document containing a single content control with the word "test", and the following code:
// In setup
Application.ActiveDocument.ContentControlOnEnter += ActiveDocument_ContentControlOnEnter;
private void ActiveDocument_ContentControlOnEnter(Word.ContentControl ContentControl)
{
var selRange = _Application.Selection.Range;
_logger.Debug(m => m("Selection: {0}-{1}", selRange.Start, selRange.End));
}
//Later in another method
var finder = _Application.ActiveDocument.Range().Find;
_logger.Debug("Find.Execute start");
finder.Execute("test);
_logger.Debug("Find.Execute end");
The following gets logged:
38137 [VSTA_Main] DEBUG - Find.Execute start
38141 [VSTA_Main] DEBUG - Selection: 1-5
38149 [VSTA_Main] DEBUG - Find.Execute end
We have a lot of code that handles ContentControlOnEnter and ContentControlOnExit events, and having the find operation cause them to be called is really causing problems!
Is there any way to use Find.Execute without having it trigger these events? Failing that, is there a good way to distinguish between the Find-triggered ones and the genuine user ones? I have tried using the time between the enter and exit events, but this is not reliable.
I had similar problems in Word, though it was about the Selection event. I tried many solutions, but only one helped. In your case, make a new field bool _skipEnterAndExitEvents and set it true before calling
finder.Execute("test) and false after calling. And in the enter and exit event handlers check this field, if the field is true then just skip. This solutions is not beautiful, looks like a hack, but other solutions are even uglier and don't really work.
I think I found a decent solution:
private bool _doIgnoreNextExit = false;
private void ActiveDocument_ContentControlOnEnter(Word.ContentControl ContentControl)
{
if (Application.Selection.Find.Found)
{
_logger.Debug("Ignoring CC enter event caused by Find operation");
_doIgnoreNextExit = true;
return;
}
// Do things
}
private void ActiveDocument_ContentControlOnExit(Word.ContentControl ContentControl)
{
if(_doIgnoreNextExit)
{
_logger.Debug("Ignoring fake exit");
_doIgnoreNextExit = false;
return;
}
// Do things
}

Using the Selection service on something that is *not* a JFace view

I am building an image Editor as an Eclipse plugin.
I would like to use the Properties view to view & edit properties of the model underneath the image. Accordingly I am calling ..
getSite().setSelectionProvider( this );
.. within createPartControl, and implementing the ISelectionProvider interface in my EditorPart implementation, so that the model is returned as the selection (which must therefore implement the ISelection interface).
The next step is for the Editor to implement IAdaptable to supply an adapter for the selected object.
My problem however is that getAdapter is never called with IPropertySource.class, and therefore the Properties View never gets what it needs to make sense of the image model.
Your help is much appreciated.
M.
The answer in the end broke down into a few pieces ...
1.) When your selection does change (if a user has zoomed into the image, for example) be sure to tell Eclipse this. It won't happen otherwise.
2.) When sending your SelectionChangedEvent, wrap up your IAdaptable in a StructuredSelection object - otherwise the Properties view will ignore it.
This boiled down to the following method
public void fireSelectionChanged()
{
final SelectionChangedEvent event = new SelectionChangedEvent( this, new StructuredSelection( this ) );
Object[] listeners = selectionChangedListeners.getListeners();
for (int i = 0; i < listeners.length; ++i)
{
final ISelectionChangedListener l = (ISelectionChangedListener) listeners[i];
SafeRunnable.run(new SafeRunnable() {
public void run() {
l.selectionChanged( event );
}
});
}
}
... on an class that implemented ISelectionProvider & IAdaptable.
M.