I'm writing a simple browser in Vala and WebKitGTK+.
One of the things I need to do is set the window's title to that of the webpage title, so I monitor title changes with web_view.notify["title"].connect. However, sometimes the value of title is null, when it obviously shouldn't be.
Some examples I remember:
Search anything in Google. Going to the next results page sets the title to null.
Click on an anchor link (e.g. http://example.com/page.html#section)
In any case, using the Web Inspector shows that the pages do have a title set.
Is this a bug I should report? Or maybe I'm doing something wrong? Here's the code I'm using:
//valac --thread --pkg webkitgtk-3.0 --pkg gtk+-3.0 --vapidir=./ test.vala
//The vapidir folder should have webkitgtk-3.0.vapi and webkitgtk-3.0.deps
using WebKit;
using Gtk;
public class Test : Gtk.Window {
public WebView webview;
public Test () {
this.title = "Test";
this.window_position = Gtk.WindowPosition.CENTER;
this.set_default_size (800, 600);
this.hide_titlebar_when_maximized = false;
this.destroy.connect (() => {
Gtk.main_quit ();
});
var scroll = new ScrolledWindow (null, null);
this.webview = new WebView ();
this.add (scroll);
scroll.add (webview);
webview.settings.enable_developer_extras = true;
webview.notify["title"].connect ((sender, property) => {
if (webview.title != null) {
this.title = webview.title;
stdout.printf (webview.title + "\n");
} else {
stdout.printf ("(null)\n");
}
});
webview.web_inspector.inspect_web_view.connect ((p0) => {
var w = new Window ();
w.window_position = WindowPosition.CENTER;
w.title = "Inspector";
w.set_default_size (800,600);
WebView view = new WebView ();
unowned WebView view2 = view;
w.add (view2);
w.show_all ();
return view2;
});
}
public static int main (string[] args) {
Gtk.init (ref args);
Test app = new Test ();
app.webview.load_uri ("http://google.com");
app.show_all ();
Gtk.main ();
return 0;
}
}
There is a signal called title_changed for that purpose and you should always use the signals provided by webkitgtk instead of the GLib notify feature.
(GLib notify is emitted each time a value changes, even if the change is just for the purpose of clearing the old value, such as in your case.)
Related
Old question: Codename One app not provide real location
We still have problem getting current location.
Sometimes it's ok, "Localizzazione..." dialog shows, then location ok callback dispose the dialog.
Sometimes the dialog is never disposed and I don't see GPS in the top bar, which is visible when location is ok and dispose the dialog.
Slider s1 = new Slider();
Display.getInstance().callSerially(() -> {
blocco_loc_in_corso = makeDialog("Localizzazione...", s1, null, 'a');
blocco_loc_in_corso.show();
});
LocationManager locationManager = LocationManager.getLocationManager();
locationManager.setLocationListener(new LocationListener() {
#Override
public void locationUpdated(Location location) {
if(location != null) {
Display.getInstance().callSerially(() -> {
if(blocco_loc_in_corso != null) {
blocco_loc_in_corso.dispose();
}
});
paintLocation(location, true);
}
}
#Override
public void providerStateChanged(int newState) {
}
}, new LocationRequest(LocationRequest.PRIORITY_HIGH_ACCUARCY, 1000));
I have this problem for at least 6 months. We only need to block user until we have his GPS location which may can change (GPS updates callback).
Edited:
public Dialog makeDialog(String label, Component c, String buttonText, char btIcon) {
Dialog dlg_r = new Dialog();
Style dlgStyle = dlg_r.getDialogStyle();
dlgStyle.setBorder(Border.createEmpty());
dlgStyle.setBgTransparency(255);
dlgStyle.setBgColor(0xffffff);
Label title = dlg_r.getTitleComponent();
title.getUnselectedStyle().setFgColor(0xff);
title.getUnselectedStyle().setAlignment(Component.LEFT);
dlg_r.setLayout(BoxLayout.y());
Label blueLabel = new Label(label);
blueLabel.setShowEvenIfBlank(true);
blueLabel.getUnselectedStyle().setBgColor(0xff);
blueLabel.getStyle().setFgColor(0x0a0afc);
blueLabel.getStyle().setAlignment(Component.CENTER);
blueLabel.getUnselectedStyle().setPadding(1, 1, 1, 1);
blueLabel.getUnselectedStyle().setPaddingUnit(Style.UNIT_TYPE_PIXELS);
dlg_r.add(blueLabel);
dlg_r.add(c);
if (buttonText != null) {
Button dismiss = new Button(buttonText);
dismiss.getAllStyles().setBorder(Border.createEmpty());
dismiss.getAllStyles().setFgColor(0);
dismiss.getAllStyles().set3DText(true, true);
dismiss.setIcon(FontImage.createMaterial(btIcon, dismiss.getStyle()));
dismiss.addActionListener(((evt) -> {
dlg_r.dispose();
}));
dlg_r.add(dismiss);
}
return dlg_r;
}
To make sure this code is threadsafe make the following change:
public void locationUpdated(Location location) {
locationFound = true;
// ...
}
Then in the make dialog method:
dlg_r.addShowListener(e -> {
if(locationFound) {
dlg_r.dispose();
}
});
Since this event can happen in the dead time of showing the dialog transition.
The documentation shows this C# snippet:
async void DisplayDeleteFileDialog(){
ContentDialog deleteFileDialog = new ContentDialog{
Title = "Delete file permanently?",
Content = "If you delete this file, you won't be able to recover it. Do you want to delete it?",
PrimaryButtonText = "Delete",
CloseButtonText = "Cancel"
};
ContentDialogResult result = await deleteFileDialog.ShowAsync();
// Delete the file if the user clicked the primary button.
/// Otherwise, do nothing.
if (result == ContentDialogResult.Primary) {
// Delete the file.
}
else {
// The user clicked the CLoseButton, pressed ESC, Gamepad B, or the system back button.
// Do nothing.
}
}
What I'm requesting is a C++/winRT version of this snippet.
IAsyncAction Async()
{
ContentDialog dialog;
dialog.Title(box_value(L"title"));
dialog.Content(box_value(L"content"));
dialog.PrimaryButtonText(L"primary");
dialog.CloseButtonText(L"close");
auto result = co_await dialog.ShowAsync();
if (result == ContentDialogResult::Primary)
{
}
}
I wanted to open content dialog on button click so I tried the code snippet provided by Kenny Kerr. Everything seemed to work fine without error but when i clicked the button no dialog was seen. i fixed it by placing below code
dialog.XamlRoot(myButton().XamlRoot());
Before auto result = co_await dialog.ShowAsync() line.
ContentDialog.xaml, xaml.h, xaml.cpp should not have the name or classes
named Windows::UI::Xaml::Controls::ContentDialog!!! My name is
ContentDialog1
DirectXPage.xaml.cpp
void YourNamespace::DirectXPage::UpdateStatus(String^ strMessage,
NotifyType type)
{
switch (type)
{
case NotifyType::StatusMessage:
StatusBorder->Background = ref new
SolidColorBrush(Windows::UI::Colors::Green);
break;
case NotifyType::ErrorMessage:
StatusBorder->Background = ref new
SolidColorBrush(Windows::UI::Colors::Red);
break;
default:
break;
}
StatusBlock->Text = strMessage;
// Collapse the StatusBlock if it has no text to conserve real estate.
if (StatusBlock->Text != "")
{
StatusBorder->Visibility = Windows::UI::Xaml::Visibility::Visible;
StatusPanel->Visibility = Windows::UI::Xaml::Visibility::Visible;
}
else
{
StatusBorder->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
StatusPanel->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
}
// Raise an event if necessary to enable a screen reader to announce
the status update.
auto peer = dynamic_cast<FrameworkElementAutomationPeer^>
(FrameworkElementAutomationPeer::FromElement(StatusBlock));
if (peer != nullptr)
{
peer->RaiseAutomationEvent(AutomationEvents::LiveRegionChanged);
}
}
void YourNameSpace::DirectXPage::NotifyUser(Platform::String^ strMessage,
NotifyType type)
{
if (Dispatcher->HasThreadAccess)
{
UpdateStatus(strMessage, type);
}
else
{
Dispatcher->RunAsync(CoreDispatcherPriority::Normal, ref new
DispatchedHandler([strMessage, type, this]()
{
UpdateStatus(strMessage, type);
ContentDialog1^ dlg = ref new ContentDialog1();
dlg->ContentDialog_SetTitle(L"Error Message");
dlg->ContentDialog_SetTextBlock(L"All textures must be chosen from
the x64\\Release or Debug\\YourNamespace\\AppX\\Assets\\
(Folder or sub-Folders)");
Windows::Foundation::IAsyncOperation<ContentDialogResult>^ result =
dlg->ShowAsync();
if (result->GetResults() == ContentDialogResult::Primary) {}
if (result->GetResults() == ContentDialogResult::Secondary) {}
}));
}
}
I want to show some pages in the first time app is installed, and the next time when I open the app show some other pages.
I tried this code
protected override void OnStart()
{
if (Application.Current.Properties.ContainsKey("id"))
{
MainPage = new NavigationPage(new Page2());
}
else
{
Application.Current.Properties["id"] = 2;
MainPage = new NavigationPage(new Page1());
}
}
The values in the Properties dictionary are only stored when the app goes to sleep
For a cross-platform approach, you can use the Settings Plugin
Then you can create a boolean property, for example, DidOpenOnce, and if it is false, show your initial welcome page or whatever. Then afterwards, set it to true.
protected void checkApplicationInstallState()
{
//retreive
var prefs = Application.Context.GetSharedPreferences("MyApp", FileCreationMode.Private);
var somePref = prefs.GetBool("IsApplicationOpenedForOnce", null);
if (!somePref) {
// Your Application is opened for the very first time. Now change the value to true as you have now opened the app so next time opening this application should get a true value.
var prefEditor = prefs.Edit();
prefEditor.PutBool(true, "IsApplicationOpenedForOnce");
prefEditor.Commit();
}
}
public MainPage()
{
InitializeComponent();
if (Application.Current.Properties.ContainsKey("FirstUse"))
{
//Do things when it's NOT the first use...
loadinit();
}
else
{
Application.Current.Properties["FirstUse"] = false;
//Do things when it IS the first use...
}
}
public async void loadinit()
{
await Navigation.PushAsync(new LoadPage());
}
I have been trying to receive mouse events on my Gtk.DrawingArea, using Vala, with no success. Specifically I am sub-classing Gtk.DrawingArea and in my constructor I add the events I want to receive:
this.add_events (Gdk.EventMask.ENTER_NOTIFY_MASK |
Gdk.EventMask.BUTTON_PRESS_MASK);
Then, in the same constructor below, I register signal handlers for these events:
this.enter_notify_event.connect (
(page, event) => {
stdout.printf("mouse entered !!! \n");
return true;
}
);
this.button_press_event.connect (
(page, event) => {
stdout.printf("mouse click \n");
return false;
}
);
I tried both return true and return false to check what happens in both cases. However I see no messages on the console when I move the pointer on the Gtk.DrawingArea or when I click on it. I even set the events for the top Gtk.Window:
this.set_events (this.get_events() |
Gdk.EventMask.ENTER_NOTIFY_MASK |
Gdk.EventMask.BUTTON_PRESS_MASK);
but the events don't seem to get received. What could be going wrong?
Your code seems correct although it's not a MVCE. I would point out the callback handlers prototype as being incorrect but since you're not using event data it should not be a "problem". The callback prototypes for enter_notify_event and button_press_eventonly supply the event, so the page argument it's incorrect.
Anyway, i tested with a very simple and raw code and it worked. Please verify:
using Gtk;
public class MyWidget : Gtk.DrawingArea {
public MyWidget () {
this.set_events (Gdk.EventMask.ENTER_NOTIFY_MASK |
Gdk.EventMask.BUTTON_PRESS_MASK);
this.enter_notify_event.connect ((event) => {
stdout.printf ("mouse entered !!! \n");
return false;
});
this.button_press_event.connect ((event) => {
stdout.printf("mouse click \n");
return false;
});
}
}
public void main (string[] args) {
Gtk.init (ref args);
var window = new Gtk.Window ();
window.add (new MyWidget ());
window.destroy.connect (Gtk.main_quit);
window.show_all ();
Gtk.main ();
}
Compile with valac test.vala --pgk gtk+-3.0.
The result is:
Using Vala 0.30.2 and Gtk+ 3.18 on Fedora 23.
I need to make instrument, that allows users to choose photo from Gallery. After choosing photo, it will be shown to the user in ImageBox.
Problem is, that when user chooses some photo in Gallery, Gallery closes, ImageBox stays empty. Code returns no error. Please help me to find error and solve this problem. Thank you.
Here is a code:
ImagePath = String.Empty
filePicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary
filePicker.ViewMode = PickerViewMode.Thumbnail
' Filter to include a sample subset of file types
filePicker.FileTypeFilter.Clear()
filePicker.FileTypeFilter.Add(".bmp")
filePicker.FileTypeFilter.Add(".png")
filePicker.FileTypeFilter.Add(".jpeg")
filePicker.FileTypeFilter.Add(".jpg")
filePicker.PickSingleFileAndContinue()
Dim BitmapImage = New BitmapImage()
Await BitmapImage.SetSourceAsync(filePicker)
MyPhoto.Source = BitmapImage
If you are using filePicker.PickSingleFileAndContinue() you need to add code into the App_Activated
You will notice that PickSingleFileAndContinue() is a void method will not return the picked file were as PickSingleFileAsync() will return a file.
Code block is in C#,sorry i have only limited knowledge in vb, you can find vb sample below
Similar SO Answer
C#
FileOpenPicker openPicker = new FileOpenPicker();
openPicker.ViewMode = PickerViewMode.Thumbnail;
openPicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
openPicker.FileTypeFilter.Add(".jpg");
openPicker.FileTypeFilter.Add(".jpeg");
openPicker.FileTypeFilter.Add(".png");
StorageFile file = await openPicker.PickSingleFileAsync();
As your are using PickSingleFileAndContinue() you need to implement ContinuationManager that were you get the file you picked.
In the App.xaml.cs
public ContinuationManager ContinuationManager { get; private set; }
This will fire when the app get activated
protected async override void OnActivated(IActivatedEventArgs e)
{
base.OnActivated(e);
continuationManager = new ContinuationManager();
Frame rootFrame = CreateRootFrame();
await RestoreStatusAsync(e.PreviousExecutionState);
if(rootFrame.Content == null)
{
rootFrame.Navigate(typeof(MainPage));
}
var continuationEventArgs = e as IContinuationActivatedEventArgs;
if (continuationEventArgs != null)
{
Frame scenarioFrame = MainPage.Current.FindName("ScenarioFrame") as Frame;
if (scenarioFrame != null)
{
// Call ContinuationManager to handle continuation activation
continuationManager.Continue(continuationEventArgs, scenarioFrame);
}
}
Window.Current.Activate();
}
Usage in the page
Assume that one page of your app contains code that calls a FileOpenPicker to pick an existing file. In this class, implement the corresponding interface from the ContinuationManager helper class. When your app uses a FileOpenPicker, the interface to implement is IFileOpenPickerContinuable.
public sealed partial class Scenario1 : Page, IFileOpenPickerContinuable
{
...
//inside this you have this
private void PickAFileButton_Click(object sender, RoutedEventArgs e)
{
...
FileOpenPicker openPicker = new FileOpenPicker();
openPicker.ViewMode = PickerViewMode.Thumbnail;
openPicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
openPicker.FileTypeFilter.Add(".jpg");
openPicker.FileTypeFilter.Add(".jpeg");
openPicker.FileTypeFilter.Add(".png");
// Launch file open picker and caller app is suspended
// and may be terminated if required
openPicker.PickSingleFileAndContinue();
}
}
switch (args.Kind)
{
case ActivationKind.PickFileContinuation:
var fileOpenPickerPage = rootFrame.Content as IFileOpenPickerContinuable;
if (fileOpenPickerPage != null)
{
fileOpenPickerPage.ContinueFileOpenPicker(args as FileOpenPickerContinuationEventArgs);
}
break;
...
}
Download msdn sample here
Msdn documentation using FilePicker