When I using java there are something like double bracket initialization that actually make some runtime trade off. In scala I discover the simple way to initiate object property like
val button1: Button = new Button
button1.setText("START")
button1.setPrefWidth(100)
Which can be rewriten to
val button2: Button = new Button {
setText("PAUSE")
setPrefWidth(100)
}
Is these make any difference from performance or something else?
The difference is that in the first case you instantiate a new Button object and set its properties to some values (text = "START" and width = 100) and in the second case you create an anonymous class that inherits from Button and initialize its properties in its anonymous initializer (or constructor, not sure - Java's anonymous classes cannot have constructors).
The second case can be roughly rewritten like this (if it weren't an anonymous class):
class MyButton extends Button {
//constructor
setText("START")
setPrefWidth(100)
}
And when you call new MyButton you get an instance of MyButton with text set as "START" and prefWidth set as 100.
If you come from Java background consider this analogy:
Button button = new Button() {
//anonymous initializer
{
setText("START");
setPrefWidth(100);
}
};
Related
I'm wondering what is a good solution to keep track of different objects of same type.
I have this function:
private extension MenuButtonsViewController {
// TODO: Find a way to find correct button based on MenuItem
func buttonFor(for menuItem: MenuItem) -> EmojiButton? {
guard let subViews = stackView.subviews as? [EmojiButton] else {
return nil
}
let button = buttonFactory.makeEmojiButton(title: menuItem.icon)
for subView in subViews where subView == button {
return subView
}
return nil
}
}
I have an array (UIStackView) with a varying number of buttons (EmojiButton). The buttons are created with content from MenuItem.
I'm looking for a good and clean solution how to find and remove a particular button from the stackView array, based on a MenuItem.
So far I had three ideas:
To create a new object, initalized with same values as the one to remove, and then match using ==. (Solution above). This didn't work.
To add an id to all buttons, and then a corresponding id to the MenuItem object. But this doesn't seem like an elegant solution to have to add that everywhere, and expose this variable from the button object.
Maybe store the button in a wrapper class (like MenuItemButton) with an id to match to, or by storing the MenuItem object so I can match against that.
Any ideas? How is this usually done?
If MenuItem and EmojiButton inherit from UIView, you can make use of the tag property that is available on all UIView's.
You first need to assign a unique tag value to each of your MenuItem's.
You then need to assign this same value to the corresponding Emoji button's tag property. (This would be a good thing to do in your factory.)
Having done that, you can modify your function as follows:
//assumes MenuItem and EmojiButton inherit from UIView
func buttonFor(for menuItem: MenuItem) -> EmojiButton? {
return stackView.viewWithTag(menuItem.tag) as? EmojiButton
}
I have a simple Form MyCustomForm, in a Form's Button in Clicked method I call a Class (method run), so I want to lock (or block) this form during run execution.
My code is look like this :
void clicked()
{// in Button clicked in **MyCustomForm**
MyClass myClass;
super();
myClass = new MyClass();
// here I want to freeze my FORM
myClass.run();
// here I want to unlock my Form
}
I need this because when class (MyClass) is running can display Dialog etc, but I don't want to touc/click and other on MyCustomForm
If I use :
element.wait(); // not work well - block all
myClass.run();
Thanks,
enjoy.
If your class displays dialog you can make this dialog modal using the following line of code dialog.parmIsModal(true).
Or formRun.wait(true) for forms.
I have a button that's created via a NIB file. I've derived a class from UIButton, replaced the class name in the NIB file.
Now my button displays with no background. The text is there, the text font and color are right, and it reacts to taps as expected, but it's as if the background is transparent. In the NIB, it's not transparent - I did not change any of the properties other than the class name.
The subclass is trivial - it overrides nothing (for now). Please, what am I doing wrong?
The reason I need a subclass of UIButton is because I want to be able, under certain circumstances, to drag text from the button to elsewhere. If there's an alternative way to handle drag and drop in a UIKit provided view, I'm willing to hear.
Check the states of the button in your NIB file.
It's possible that you are looking at the "active" state or something rather than the more common UICONTROLSTATENORMAL.
Honestly not sure what's wrong with the subclass, but the 'Net (including SO) is full of cautionary tales about subclassing UIButton, and how you shouldn't.
So I'll go with method swizzling on the four touch processing methods. The following function replaces the provided method of a button with my implementation (taken from the MyButton class), while saving the old one in the system button class under a different selector:
//Does NOT look at superclasses
static bool MethodInClass(Class c, SEL sel)
{
unsigned n,i ;
Method *m = class_copyMethodList(c, &n);
for(i=0;i<n;i++)
{
if(sel_isEqual(method_getName(m[i]), sel))
return true;
}
return false;
}
static void MountMethod(Class &buc, SEL SrcSel, SEL SaveSlotSel)
{
IMP OldImp = [buc instanceMethodForSelector:SrcSel];
IMP NewImp = [[MyButton class] instanceMethodForSelector:SrcSel];
if(OldImp && NewImp)
{
//Save the old implementation. Might conflict if the technique is used
//independently on many classes in the same hierarchy
Method SaveMe = class_getInstanceMethod(buc, SaveSlotSel);
if(SaveMe == NULL)
class_addMethod(buc, SaveSlotSel, OldImp, "v#:##");
else
method_setImplementation(SaveMe, OldImp);
//Note: the method's original implemenation might've been in the base class
if(MethodInClass(buc, SrcSel))
{
Method SrcMe = class_getInstanceMethod(buc, SrcSel);
if(SrcMe)
method_setImplementation(SrcMe, NewImp);
}
else //Add an override in the current class
class_addMethod(buc, SrcSel, NewImp, "v#:##");
}
}
And call it so:
Class buc = [bu class];
MountMethod(buc, #selector(touchesBegan:withEvent:), #selector(MyButton_SavedTouchesBegan:withEvent:));
MountMethod(buc, #selector(touchesCancelled:withEvent:), #selector(MyButton_SavedTouchesCancelled:withEvent:));
MountMethod(buc, #selector(touchesEnded:withEvent:), #selector(MyButton_SavedTouchesEnded:withEvent:));
MountMethod(buc, #selector(touchesMoved:withEvent:), #selector(MyButton_SavedTouchesMoved:withEvent:));
This has the disadvantage of mounting the said methods for all buttons, not just for the ones desired. In the MyButton's implementation, there's an additional check if the drag-drop functionality is to be enabled for this particular button. For that I've used associated objects.
One fine point is that touchesXXX methods are implemented in the UIControl class, not in the UIButton. So my first, naive implementation of swizzling would replace the method in UIControl instead of the button class. The current implementation does not assume either way. Also, it makes no assumptions about the run-time class of buttons. Could be UIButton, could be anything (and in real iOS, it's UIRoundedRectButton).
I am trying to code a flash app entirely in the document class. I am using GestureWorks with a touch screen. When a user essentially presses a button it calls a method that should hide a specific graphic but not the graphic they touched.
Essentially I need a way to refer to a graphic on the screen using a method besides 'e.target'.
I am receiving this error: Error #1009: Cannot access a property or method of a null object reference.
//This code works
private function photo1SpriteFlickHandler(e:GestureEvent):void {
var openTween:Tween = new Tween(e.target, "x", Strong.easeOut, 232, 970, 5, true);
}
//this code gives me a null object reference
private function photo1SpriteFlickHandler(e:GestureEvent):void {
var openTween:Tween = new Tween(photo1Sprite, "x", Strong.easeOut, 232, 970, 5, true);
}
//photo1Sprite has already been programatically added to the screen as so:
var photo1Sprite = new TouchSprite();
var photo1Loader=new Loader();
photo1Loader.load(new URLRequest("media/photos1/photo1.jpg"));
photo1Loader.contentLoaderInfo.addEventListener(Event.COMPLETE,loaderComplete);
photo1Sprite.x = 232;
photo1Sprite.y = 538;
photo1Sprite.scaleX = .3;
photo1Sprite.scaleY = .3;
photo1Sprite.blobContainerEnabled = true;
photo1Sprite.addEventListener(TouchEvent.TOUCH_DOWN, startDrag_Press);
photo1Sprite.addEventListener(TouchEvent.TOUCH_UP, stopDrag_Release);
photo1Sprite.addChild(photo1Loader);
addChild(photo1Sprite);
It can access photo1Sprite as 'e.target' when the button click happens on the photo1Sprite.
The problem happens when to click one button (not photo1Sprite) and have it effect photo1Sprite.
So I can make photo1Sprite react if my method is attached to it directly using 'e.target' but not if I am trying to call it from a method that was called from another element on the screen.
I'm not sure what the Tween class constructor expects as it first argument. Is it a Sprite instance or is it the name of a Sprite instance? In any case make sure that - in the context of photo1SpriteFlickHandler - photo1Sprite is 1) defined! and 2) refers to the correct thing.
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.