Showing more than one line of the notification description in the notification tray using an extension - gnome-shell

I am currently designing an extension to make the notifications in the notification section of the calendar expendable. The goal is to make the noficiation expand like the initial notification on the desktop does. I have changed the type of notification added to the noficiation tray to class NotificationBanner from class NotificationMessage. I am currently using a work-around to make this work, this is what my expand function looks like:
expand(animate) {
this.expanded = true;
this._actionBin.visible = this._actionBin.get_n_children() > 0;
if (this._bodyStack.get_n_children() < 2) {
this._expandedLabel = new MessageList.URLHighlighter(this._bodyText,
true, this._useBodyMarkup);
this.setExpandedBody(this._expandedLabel);
}
if (animate) {
if (!this.clickedByButton && !this.forceExpansion) {
// This is the usual way notifications are expanded, using the layout manager
this._bodyStack.ease_property('#layout.expansion', 1, {
progress_mode: Clutter.AnimationMode.EASE_OUT_QUAD,
duration: MessageTray.ANIMATION_TIME,
});
}
else if (this.forceExpansion || this.clickedByButton) {
// When auto expanding or clicked by button, change height of body
oldHeight = this.bodyLabel.get_height();
const lines = Math.ceil(this._bodyText.length / 54);
this.bodyLabel.set_height(lines * this.bodyLabel.get_height());
}
this._actionBin.scale_y = 0;
this._actionBin.ease({
scale_y: 1,
duration: MessageTray.ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
});
} else {
this._bodyStack.layout_manager.expansion = 1;
this._actionBin.scale_y = 1;
}
this.emit('expanded');
}
As you can see, I have 2 options for this extension: Force expand all notifications or make the user use a button to expand. The current solution is not elegant, it simply changes the height of the notification label which manages the body. Furhermore, the notification body still shows the three dots, implying that the body is still not expanded. I believe this to be an issue with the layout manager, since the proper way to expand is to set message._bodyStack.layout_manager.expansion to 1. That does not work in the case of expanding a message in the notification tray. Is anyone familiar with the layout manager or can help me find a different solution? Here is an image of what my current solution looks like:
Image of an automatically expanded notification in the notification tray due to the extension (note the three dots at the end of the first line being still there)

Okay I have found a solution, it is not related to the layout manager. The value of the message message.bodyLabel.clutter_text.ellipsize is set to 3, which is the main cause of the dots appearing on the notification. Setting this value to 0 solves this problem. I would have still loved to find a more elegant approach to displaying the body, but this will do.

Related

nativescript - change variable on exitEvent

I need to be able to change some variable's value, when app is closed.
I'm using exitEvent described here:
https://docs.nativescript.org/core-concepts/application-lifecycle
Also, i'm using local-storage plugin that works similar to javasctip's localstorage.
https://github.com/NathanaelA/nativescript-localstorage
My simple code looks like this:
var Observable = require("data/observable").Observable;
require("nativescript-dom");
var LS = require("nativescript-localstorage");
const application = require("tns-core-modules/application");
var page = require("ui/page");
exports.load = function (args) {
var page = args.object;
var model = new Observable();
var frame = require('ui/frame');
var ff = frame.getFrameById("dashboard");
var topmost = frame.topmost();
// This is exit event
application.on(application.exitEvent, (args) => {
LS.setItem('XX','111')
});
// What i will exit app, and run app again this will newer become 111,
it's null all the time
console.log(LS.getItem('XX'));
}
So, my question is - is possible to set any flag on app exit - it do not have to be localstorage (i've tested global variables to), to detect if exit was made, and based on this i can make a decisions that will help me ?
One of scenarios may be - i'm holding some flag in Localstorage that is TURE is user tapped "rememebr me" on the login screen.
So on exit i can check if he want's to be rememebered, if not i want to send user to login page and not dashboard when app is lauching....
Thank you.
EDIT:
I've tried applications-settings too, it will not work.
application.on(application.exitEvent, (args) => {
applicationSettings.setString("Name", "John Doe");
});
console.log(applicationSettings.getString("Name")); // not working
I suspect it's the issue with the nativescript-localstorage plugin. It writes the changes to file after a 250ms delay. At exit event you will give you very limited amount of time before your app is completely killed by system.
May be the Author had a reason for setting up this delay but I think its too much of time at least in this particular scenario so the changes are never written to file. You may raise a issue at the plugin's Github repo.
If you are looking for an immediate workaround, copy localstorage.js to your app and export internalSaveData from the file, so you could directly call it right after you finish setting your values.

Optimizely Sticky Session

I have just tried Optimizely. The problem is it will show different variations to a user. Sometimes we don't expect this behaviour. For example if I change color to red from blue, Optimizely will randomly select between the orginal (blue) and the variation (red) for the same user which is inconsistent. How can I make Optimizely to always show the same variation to a user?
Place the following code in your Experiment JavaScript:
setCookie = function (c_name,value,exdays) {
var exdate=new Date();
exdate.setDate(exdate.getDate() + exdays);
var expires = exdate.toUTCString();
var isIE8 = (document.documentMode !== undefined);
if (exdays == 0) {
expires = (isIE8 == true) ? "" : "0";
}
var c_value=escape(value) + ((exdays==null) ? "" : "; expires="+expires);
document.cookie=c_name + "=" + c_value;
}
Within each variant (e.g. Blue Variant, Red Variant, etc.), call setCookie and check whether the cookie exists for a user in that particular variant. If the cookie does exist, then run whatever code you want that particular variant to run. Below is an example of setting a cookie called tester that will expire after 30 days.
setCookie('tester',true,30);
if(document.cookie.indexOf('tester')>-1){
//RUN YOUR CODE HERE IF THIS VISITOR HAS THIS COOKIE
}
Hi there I am an engineer at Optimizely,
You could alternatively try the Fullstack product, which is more developer-oriented. With this you get an SDK that you install with your bundle and you implement your testing logic using code.
Example:
npm install optimizely-client-sdk
const optimizely = require('optimizely-client-sdk');
const optimizelyClient = optimizely.createInstance({
datafile: {} // this is your experiment config which you get from the Optimizely UI
});
const variation = optimizelyClient.activate('color_experiment', 'user_1');
if (variation === 'blue') {
// do something for blue
} else if (variation === 'red') {
// do something for red
} else {
// default case
}
And as long as you pass in the exact same user_id as the second argument to activate, you are guaranteed to always get the same variation for that user.
For more information or details on getting started please take a look at: https://developers.optimizely.com/x/solutions/sdks/getting-started/index.html?language=javascript
Also keep in mind that Optimizely gets blocked by adblockers, it can happen if a user turns their adblocker on after they've been on the page and served up an experiment to see - they would get the original version.

Flixel Game Over Screen

I am new to game development but familiar with programming languages. I have started using Flixel and have a working Breakout game with score and lives.
I am just stuck on how I can create a new screen/game over screen if a player runs out of lives. I would like the process to be like following:
Check IF lives are equal to 0
Pause the game and display a new screen (probably transparent) that says 'Game Over'
When a user clicks or hits ENTER restart the level
Here is the function I currently have to update the lives:
private function loseLive(_ball:FlxObject, _bottomWall:FlxObject):void
{
// check for game over
if (lives_count == 0)
{
}
else
{
FlxG:lives_count -= 1;
lives.text = 'Lives: ' + lives_count.toString()
}
}
Here is my main game.as:
package
{
import org.flixel.*;
public class Game extends FlxGame
{
private const resolution:FlxPoint = new FlxPoint(640, 480);
private const zoom:uint = 2;
private const fps:uint = 60;
public function Game()
{
super(resolution.x / zoom, resolution.y / zoom, PlayState, zoom);
FlxG.flashFramerate = fps;
}
}
}
There are multiple ways to go about doing this...
You could use different FlxStates, like I described in the answer to your other post: Creating user UI using Flixel, although you'll have to get smart with passing the score or whatever around, or use a Registry-type setup
If you want it to actually work like you described above, with a transparent-overlay screen, you can try something like this (keep in mind, the exact details may differ for your project, I'm just trying to give you an idea):
First, make sure you have good logic for starting a level, lets say it's a function called StartLevel.
You'll want to define a flag - just a Boolean - that tracks whether or not the game is still going on or not: private var _isGameOver:Boolean; At the very end of StartLevel(), set this to false.
In your create() function for your PlayState, build a new FlxGroup which has all the things you want on your Game Over screen - some text, an image, and something that says "Press ENTER to Restart" (or whatever). Then set it to visible = false. The code for that might look something like:
grpGameOver = new FlxGroup();
grpGameOver.add(new FlxSprite(10,10).makeGraphic(FlxG.Width-20,FlxG.Height-20,0x66000000)); // just a semi-transparent black box to cover your game screen.
grpGameOver.add(new FlxText(...)); // whatever you want to add to the group...
grpGameOver.visible = false;
add(grpGameOver); // add the group to your State.
Depending on how your game is setup, you may also want to set the objects in your group's scrollFactor to 0 - if your game screen scrolls at all:
grpGameOver.setAll("scrollFactor", new FlxPoint(0,0));
In your update() function, you'll need to split it into 2 parts: one for when the game is over, and one for if the game is still going on:
if (_isGameOver)
{
if (FlxG.keys.justReleased("ENTER"))
{
grpGameOver.visible = false;
StartLevel();
}
}
else
{
... the rest of your game logic that you already have ...
}
super.update();
Keep in mind, if you have things that respond to user input anywhere else - like a player object or something, you might need to change their update() functions to check for that flag as well.
Then, the last thing you need to do is in your loseLive() logic:
if (lives_count == 0)
{
_isGameOver = true;
grpGameOver.visible = true;
}
else
...
That should do it!
I would highly recommend spending some time with different tutorials and sample projects to kind of get a better feel for Flixel in general. Photon Storm has some great material to play with (even though he's jumped over to HTML5 games)
I also want to note that if you get comfortable with the way Flixel handles updates, you can get really smart with your state's update() function and have it only call update on the grpGameOver objects, instead of having to change all your other objects updates individually. Pretty advanced stuff, but can be worth it to learn it.

How to display Images in a wxListCtrl (multicolumn report style)

I already managed to create wxListCtrls with either icons or multicolumn text like this
Picture of two wxListCtrls
Now I'd like to add an icon to each line of the text list on the left. I thought this should be possible as typical wxWidgets applications like code::blocks and wxSmith often diplay icons in list/tree views (resource browser window) and even in tabs of notebooks (compiler log window).
So how can I create something like this? (Everybody knows Windows Explorer)
Picture of Explorer Window with icons
I tried this...
SetImageList (ToolImages, wxIMAGE_LIST_NORMAL);
InsertColumn (0, "Icon");
SetColumnWidth (0, 40);
...
for (int i=0; i<5; i++)
{
InsertItem (i, i);
SetItemColumnImage (i, 0, i);
SetItem (i, 1, IntToStr (i+1));
...
But as you can see, only the text gets displayd, the image column is blank. Is it possible at all to mix text and images in report mode? If not, what other wxControl class can I use to get the desired result?
Many Thanks in advance.
Yes, it is possible, and the listctrl sample shows how to do it, in particular see MyFrame::InitWithReportItems() function. The only difference with your code seems to be that you use a different InsertItem() overload, so perhaps you should use InsertItem(i, "") instead.
Also check that your image list does have the 5 icons in it.
More generally, trying to reduce the differences between your code and the (working) sample will almost always quickly find the problem.
Thanks, VZ, but I found out that it's not the InsertItem() but the SetImageList(). My image list was correct, but the "which" parameter wasn't. Replacing wxIMAGE_LIST_NORMAL by wxIMAGE_LIST_SMALL fixes the problem! I thought "SMALL" was only meant for the SMALL_ICON mode and that "NORMAL" should be the default. But yes, that makes sense, normal icons are big and don't fit in the text display. Would be nice if the documentation had told us that before long trial and error...
This is a simple example for SMALL ICONIC VIEW USING WXLISTCTRL .Please place this code inside the class declaration.I did it in Frame based Windows Application using CODE BLOCKS.It will be useful to you.
wxImageList *il=new wxImageList(32,32,false,0);
wxImageList *i2=new wxImageList(32,32,false,0);
wxDir dir(wxGetCwd());
wxDir dir1(wxGetCwd());
if ( !dir.IsOpened() )
{
// deal with the error here - wxDir would already log an error message
// explaining the exact reason of the failure
return;
}
if ( !dir1.IsOpened() )
{
// deal with the error here - wxDir would already log an error message
// explaining the exact reason of the failure
return;
}
puts("Enumerating object files in current directory:");
wxString path, filename, dirstring,filename1, dirstring1, img,imgPath,path1,img1,imgPath1;
int i=0;
path=wxT("C:\\testing\\splitterwindow\\set\\devices");
path1=wxT("C:\\testing\\splitterwindow\\set\\actions");
img=wxT("C:\\testing\\splitterwindow\\set\\devices\\");
img1=wxT("C:\\testing\\splitterwindow\\set\\actions\\");
bool cont=dir.Open(path);
bool cont1=dir1.Open(path1);
cont = dir.GetFirst(&filename, wxEmptyString, wxDIR_DEFAULT);
dirstring.Append(filename.c_str());
cont1 = dir1.GetFirst(&filename1, wxEmptyString, wxDIR_DEFAULT);
dirstring1.Append(filename1.c_str());
while ( cont )
{
imgPath.clear();
cont = dir.GetNext(&filename);
dirstring.Append(filename.c_str());
// Consturct the imagepath
imgPath.Append(img.c_str());
imgPath.Append(filename.c_str());
//Now, add the images to the imagelist
il->Add(wxBitmap(wxImage(imgPath.c_str())));
i++;
}
while ( cont1 )
{
imgPath1.clear();
cont1 = dir1.GetNext(&filename1);
dirstring1.Append(filename1.c_str());
// Consturct the imagepath
imgPath1.Append(img1.c_str());
imgPath1.Append(filename1.c_str());
//Now, add the images to the imagelist
i2->Add(wxBitmap(wxImage(imgPath1.c_str())));
i++;
}
//assigning the imagelist to listctrl
ListCtrl1->AssignImageList(il, wxIMAGE_LIST_SMALL);
ListCtrl3->AssignImageList(i2, wxIMAGE_LIST_SMALL);
for(int j=0;j < il->GetImageCount()-1;j++)
{
wxListItem itemCol;
itemCol.SetId(j);
itemCol.SetImage(j);
itemCol.SetAlign(wxLIST_FORMAT_LEFT);
ListCtrl1->InsertItem(itemCol);
}
for(int k=0;k < i2->GetImageCount()-1;k++)
{
wxListItem itemCol1;
itemCol1.SetId(k);
itemCol1.SetImage(k);
itemCol1.SetAlign(wxLIST_FORMAT_LEFT);
ListCtrl3->InsertItem(itemCol1);
}
`

Testing to see if a window is maximized

I noticed that in Windows, if you maximize a window you can not resize it until you un-maximized it again. This appears to be a normal behaviour, so I would like to remove my resize gripper when the window is maximised.
At the moment I can't find a property to detect if a window is maximized, and although I could add a boolean in my controller, it wouldn't necessarily catch requests to maximize from the OS.
So if you know of a reliable way to test if a window is maximized please let me know.
On a related note, I am using custom chrome, and when I maximize a window it overlaps the windows task bar. I can think of hacks to detect available screen size (using a transparent system chrome window), but it would be good to know of a better method.
Thanks
Rob
In your application (MXML) on the in the init method you ussually call on creationComplete:
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
creationComplete="init()" >
Add the following code:
this.addEventListener(NativeWindowDisplayStateEvent.DISPLAY_STATE_CHANGE, trackState);
the method looks like this:
public function trackState(event:NativeWindowDisplayStateEvent):void
{
if (event.afterDisplayState == NativeWindowDisplayState.MAXIMIZED)
{
isMaximised = true;
} else {
isMaximised = false;
}
}
I have figured out how this can best be done thanks to some pointers from TheBrain.
Firstly you need to watch for resize events to the window your want to control:
NativeApplication.nativeApplication.activeWindow.addEventListener(NativeWindowBoundsEvent.RESIZE, onWindowResize);
Then handle that event to decide if the window is maximised or not:
public function onWindowResize(event:NativeWindowBoundsEvent):void
{
if (event.afterBounds.height >= Screen.mainScreen.visibleBounds.height && event.afterBounds.width >= Screen.mainScreen.visibleBounds.width)
isMaximised = true;
else
isMaximised = false;
}
You then need to catch or create your own maximize button, and when clicked perform the following code:
if (isMaximised)
{
var bounds:Rectangle = Screen.mainScreen.visibleBounds;
NativeApplication.nativeApplication.activeWindow.bounds = bounds;
}
else
{
NativeApplication.nativeApplication.activeWindow.bounds = new Rectangle(100, 100, 500, 600);
}
You can modify the bounds to over maximize (which is handy for custom chrome windows with shadows), and you can also set the application to reset to a default size if the maximize button is clicked when it's already maximized (or do nothing).
I had issues about when to assign the window resize listner, and ended up removing and adding it every time the maximize button was clicked. It's a bit of overkill, but not too bad.
There is Win32 API Call that will do this for you:
BOOL IsZoomed( HWND hWnd );
to get the actual usable space from the screen, use the flash.display.Screen class, or you can use the systemMaxSize() which returns the largest window size allowed by the OS. For maximization you have some events that the window is dispaching when maximized/minimized/restored. You can find more info on the adobe pages (the link under systemMaxSize).
To detect if window is maximized...I don't think there is such a function (I might be wrong) but you can test if the app size is equal with the available screen size which means it's maximized. Or hook on the resize event which is triggered when the app is maximized/minimized/resized
Here is an easier way of checking if a window is maximized:
if(stage.nativeWindow.displayState == NativeWindowDisplayState.MAXIMIZED)
{
//do something
}
The following worked for me. No need to set event listeners, this code can be used to check the real-time state of the native window:
if (nativeWindow.displayState == 'maximized')
{
trace('Maximized');
}
else
{
trace('Minimized');
}
Can you use something like this to hook the maximize() event?

Resources