Move specific application to a specific screen - hammerspoon

I have read over here how to move an application to a specific screen.
In my case I have a variation of this. In this case I want to open for example Todoist on a specific screen. This code below opens Todoist but on my wrong screen.
How can I solve this?
local screens = hs.screen.allScreens()
hs.application.open("Todoist")
local win = hs.application:findWindow("Todoist")
win.moveToScreen(screens[1])

findWindow() is an instance method, so it cannot be called directly as hs.application:findWindow(). To properly call this method, you must create an instance of the hs.application class and then call findWindow() on that instance.
The following snippet should work, although you may need to adjust the wait time (and the screens index). It is generally recommended to use hs.application.watcher to watch for when an app has been launched, rather than using a timer.
local notes = hs.application.open("Notes")
hs.timer.doAfter(1, function()
-- `notes:mainWindow()` will return `nil` if called immediately after opening the app,
-- so we wait for a second to allow the window to be launched.
local notesMainWindow = notes:mainWindow()
local screens = hs.screen.allScreens()
notesMainWindow:moveToScreen(screens[1])
end)

Related

Is this a bug in the Log class in CodenameOne?

I've been trying to use the log class to capture some strange device-specific failures using local storage. When I went into the Log class and traced the code I noticed what seems to be a bug.
when I call the p(String) method, it calls getWriter() to get the 'output' instance of the Writer. It will notice output is null so it calls createWriter() create it. Since I haven't set a File URL, the following code gets executed:
if(getFileURL() == null) {
return new OutputStreamWriter(Storage.getInstance().createOutputStream("CN1Log__$"));
}
On the Simulator, I notice this file is created and contains log info.
so in my app I want to display the logs after an error is detected (to debug). I call getLogContent() to retrieve it as a string but it does some strange things:
if(instance.isFileWriteEnabled()) {
if(instance.getFileURL() == null) {
instance.setFileURL("file:///" + FileSystemStorage.getInstance().getRoots()[0] + "/codenameOne.log");
}
Reader r = new InputStreamReader(FileSystemStorage.getInstance().openInputStream(instance.getFileURL()));
The main problem I see is that it's using a different file URL than the default writer location. and since the creation of the Writer didn't set the File URL, the getLogContent method will never see the logged data. (The other issue I have is a style issue that a method getting content shouldn't be setting the location for that content persistently for the instance, but that's another story).
As a workaround I think I can just call "getLogContent()" at the beginning of the application which should set the file url correctly in a place that it will retrieve it from later. I'll test that next.
In the mean time, is this a Bug, or is it functionality I don't understand from my user perspective?
It's more like "unimplemented functionality". This specific API dates back to LWUIT.
The main problem with that method is that we are currently writing into a log file and getting its contents which we might currently be in the middle of writing into can be a problem and might actually cause a failure. So this approach was mostly abandoned in favor of the more robust crash protection approach.

titanium alloy global functions

i have a question, are the global functions set in alloy.js runs every time the app is started or every time a new window is open?
because i actually would like to create a unique user id for the user and assign it a global variable so it can be used through the app but i ain't sure if it will re-create and re-assign the generated user id whenever the app tries to open another window or will it use same user_id that the app generated after instantiating the mobile app.
hope someone could answer me. >.<
The functions in alloy.js will run every time the app is loaded, and they will load near the beginning of the execution of the app. So the answer is NO, your unique ID will NOT be re-created every time a new window opens.
From the Titanium DOC:
The initializer file app/alloy.js can be used to execute some code near the beginning of the application's lifecycle. The contents of this file will be executed right before the initial index.js controller is loaded, allowing you to execute code before any UI components are loaded and to override builtin Alloy functions before they are executed.
Also, here's an example of how to run a function and store the result in a global variable (your unique_id function would work the same way):
Alloy.Globals.myId = function(){
var id = (CODE TO GENERATE ID)
return id;
}

Create Console like Progress Window

I am replacing many batch files, that do almost the exact same thing, with one WPF executable. I have the program written, but I am having troubles with my "console" like display.
Within the program I call an executable to perform a task. This executable sends it's output messages to the console. I am able to redirect those to my "console" like display with the following.
Process p = new Process();
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = true;
p.StartInfo.FileName = MyExecutable;
p.StartInfo.Arguments = MyArguments;
p.Start();
while (!p.StandardOutput.EndOfStream)
{
string _output = p.StandardOutput.ReadLine();
// This is my display string ObservableCollection
_displayString.Add(new DisplayData { _string = _output, _color = System.Windows.Media.Brushes.Black, _fontSize = 12 });
// This is to redirect to a Console & what I want to get rid of
Console.WriteLine(_output);
}
p.WaitForExit();
When the executable is done running I use a MessageBox to ask the user if they want to run the executable again. The problem is that when the MessageBox is up the user is unable to scroll on my "console" like window to make an informative decision. To temporarily work around this I launch a console at start up, see this, and write the output stream from the process running the executable to the console so the user can scroll through the information and make a decision.
I am using a listbox to display a collection of textblocks, see this. I am not attached to anything for making the display, or MessageBox'es.
How can I make a "console" like display that will take a user input (MessageBox, direct input, etc...), but also allow them to scroll through the data before they make their decision?
EDIT:
As to the comments I have been receiving I am not clear on what I am trying to accomplish. I have a batch file that runs a executable multiple times with different arguments per run. There is a lot of setup before and between the executable calls. I have created an executable to replace many flavors of a similar batch file with drop down menus for the user to change settings at run time. When the user likes their settings they click a "Start" button, and away it goes doing setups and prompting questions as it goes and then finally runs executable for the first time.
My issue is when the called executable, inside mine, is done running the user needs to decide if they want to run it again for different reasons. I need to prompt the user "Run again - 'Yes' or 'No'?", and that is where I am running into problems. A MessageBox doesn't allow me to scroll on my Progress Window. I have tried a Modeless dialog box, but with Show() the program continues on, and ShowDialog() is the same issue as the MessageBox.
Any suggestions on how to do this would be appreciated.
You are in Windows, but trying to use DOS paradigm. Windows is event-based system! You need to write "event handlers" but not put all your code in one function.
However, there is a trick, which allows to show Modal (read "blocking your code") dialog in Modeless (read "not blocking your window"). Not sure how to implement this in WPF, but idea is to re-enable your window (which acts as parent for your dialog). You need to do this in your dialog event handler (WM_INITDIALOG equivalent?).
Also (in WinAPI) you may run dialog with NULL as parent window.

Calling .Net function on UI test instance in TestComplete

I have a simple wpf app which has a button that increments a value on clicking. I also have a function that returns the latest value. The default value is 5. I also have a UI test in testcomplete that clicks the button 3 times (so 8). I need to call the .Net function to get this value and assert it. Below is my test code.
After some search I figured out the CLRbridge details and implemented it. However, As you can see below, the UI test instance and the instance on which I am claling the function are different. So, the function returns 5.
My question is, how do I invoke the function from the same instance loaded by testcomplete. Or am I going completely the wrong way for this? I tried both script and UI test with if..then, nothing worked. I have tried both direct instance and calling on the appdomain, both doesnt seem to work.
NOTE: I do understand that I can display the value in a UI control and validate the control. However, i am specifically trying this out for a more complex testing functionality we need in a project.
function Test2()
{
var Increment;
Increment = 0;
//Runs the "TCompTest" tested application.
TestedApps.TCompTest.Run();
//Clicks the 'button1' button.
Aliases.TCompTest.HwndSource_MainWindow.MainWindow.Grid.button1.ClickButton();
//Clicks the 'button1' button.
Aliases.TCompTest.HwndSource_MainWindow.MainWindow.Grid.button1.ClickButton();
//Clicks the 'button1' button.
Aliases.TCompTest.HwndSource_MainWindow.MainWindow.Grid.button1.ClickButton();
//Increment = dotNET.Incrementer.Incr1.zctor().IntValue(true);
Increment = dotNET.Incrementer.Incr1.zctor().IntValue(true);
**OR**
Increment = Sys.Process("TCompTest").AppDomain("TCompTest.exe").dotNET.Incrementer.Incr1.zctor().IntValue(true)
// if(Increment == 8)
// {//Posts an information message to the test log.
Log.Message(Increment);
// }
//Closes the 'HwndSource_MainWindow' window.
Aliases.TCompTest.HwndSource_MainWindow.Close();
}
It should be possible to do what you need from TestComplete. But first of all, to avoid misunderstanding, let me explain the problems with the approaches you tried:
Addressing a class through the "dotNET" object.
When you do this, TestComplete initializes .NET in its service process, loads the specified assembly into it, and works with the classes of this assembly loaded to TestComplete's AppDomain (though living in a separate process). This means that this instance of your assembly has nothing to do with your tested application. So, you can't access your application's data through the dotNET object.
Addressing the Incrementer assembly through the tested application's AppDomain.
OK, in this case you are closer to a solution - you work with the AppDomain of the tested application, so you can access the application's data. However, in your code, you create a new instance of the Incr1 class (via calling zctor). This means that the new class instance will initialize its counter in the constructor, and it will be 5. And this is the value you are getting in your code.
So, the right approach:
Unless the counter field of the Incr1 class containing the current counter value is a static field, you need to address an existing object of the Incr1 class to get the current value of the property, not to create a new class instance. The actual implementation will depend on where you are storing the Incr1 class instance reference in your application. Let's suppose, you store the reference in the Counter property of the MainWindow object:
// Creating an instance of the class somewhere in your code
MainWindow.Counter = new Incr1();
// ...
// And this line of code is in the button click handler
MainWindow.Counter.Increment();
In the described case, you will be able to get the current counter value in your TestComplete script as follows:
var MainWnd = Aliases.TCompTest.HwndSource_MainWindow.MainWindow;
Log.Message(MainWnd.Counter.IntValue(true));
If your setup is different, please describe it - I will try to help accordingly.

Silverlight IsolatedStorage removed when application is shutdown?

From what I can find, seems like the IsolatedStorage supposed to be permanent unless the user delete it manually. And the following thread says so too:
Is Silverlight isolated storage treated as permanent, or as a cache?
However seems like if I shut down my application and restart it (as I am debugging on debug mode - not sure if that makes a different), the data I stored earlier is gone.
For example, just as pseudocode:
onClick =
let storage = IsolatedStorageSettings.ApplicationSettings
let x = storage.Item key
storage.Add(key, "Some Value")
on first click event, "x" is null (or empty) as expected. Then on the 2nd time around, x would have "Some Value" - this all works fine as expected. However, when I stop debugging, and restart the application, first time around, "x" goes back to null or empty. Tried the same using SiteSettings.
So seems to me IsolatedStorage is not permanent afterall? Just goes with the lifetime of the application?
1- Use the SiteSettings instead of ApplicationSettings
System.IO.IsolatedStorage.IsolatedStorageSettings.SiteSettings("YourKey")
= yourValue
2- You need to save the data after you change them
System.IO.IsolatedStorage.IsolatedStorageSettings.SiteSettings.Save()

Resources