Open web page on click at a button in a JetBrains Space chat message using Kotlin SDK - kotlin

I have a simple chat bot that renders "on this day" facts based on Wikipedia.
As you can see, there's a button on my UI. I want that if the user taps on it, a new browser tab opens with given Wikipedia url.
Until now, I only see the possibility to send other messages using buttons and there action (PostMessageAction).
Do you have any tip on how to achieve my feature idea?
Code
private fun makeMessage(container: OnThisDay): ChatMessage {
return message {
...
section {
text("On this day (${container.date}) happened:")
container.happenings.reversed().forEach {
text(
size = MessageTextSize.SMALL,
content = "${it.year}:\n${it.description}",
)
controls {
wikipediaButton(it.wikipediaUrl) <-- BUTTON
}
divider()
}
}
}
}
private fun MessageControlGroupBuilder.wikipediaButton(urlString: String) {
val action = PostMessageAction("a", "b") <-- NO other action possible?
button("Open Wikipedia", action, MessageButtonStyle.SECONDARY)
}
Screenshot

You can use NavigateUrlAction for this. Here's an example:
message {
section {
controls {
button(
text = "Open Wikipedia",
style = MessageButtonStyle.PRIMARY,
action = NavigateUrlAction(
url = "https://wikipedia.org",
withBackUrl = false,
openInNewTab = true
)
)
}
}
}

Related

Codename One location sometimes not working

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.

How to hide stacklayout if user clicked somwhere else on screen

I createt ResourceDictionary in App.xaml file for application header.
In header I created two dropdowns menu (with stacklayouts and grids).
First is for some user informations and second one is for search.
By default these dropdown menus are hiden.
Max one may be visible if user click on user-icon or on search-icon.
So in HeaderViewModel I cratet these two methods:
private async void AccountInformationAsync()
{
var userService = await UserService.GetUserData();
Username = userService.Username;
DisplayName = userService.DisplayName;
Status = userService.Status;
Influence = userService.Influence;
MTP = userService.MTP;
VisibilityInformation = !VisibilityInformation;
if (VisibilityInformation == true)
{
VisibilitySearch = false;
}
}
private void Search()
{
VisibilitySearch = !VisibilitySearch;
if (VisibilitySearch == true)
{
VisibilityInformation = false;
}
}
This works fine... If user click on user-icon user info will show up and if user then click on serach-icon info will hide an search menu will show up.
So, my question is how to hide any of these menus if user click somewhere else on the screen?
You need to add an TapGestureRecognizer on the Main Layout View of the Page. And on the Tap of it you can use Command and Hide both the dropdown Menu.
private void HideDropDowns()
{
VisibilitySearch = false;
VisibilityInformation = false;
}
HideDropDowns should be the Method assigned to the Command in the TapGestureRecognizer.

C++/winRT xaml ContentDialog example

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) {}
}));
}
}

TornadoFX - remove item with ContextMenu right click option

So I have a table view that displays an observedArrayList of AccountsAccount(name, login, pass), those are data classes. When I right click a cell there pops an option of delete. What I want to do is delete that Account from the observedArrayList
Only I can not find any way to do this. I am not experienced with JavaFX or TornadoFX and I also can't find the answer with google or in the TornadoFX guides and docs.
This is my code:
class ToolView : View() {
override val root = VBox()
companion object handler {
//val account1 = Account("Google", "martvdham#gmail.com", "kkk")
//val account2 = Account("Google", "martvdham#gmail.com", "Password")
var accounts = FXCollections.observableArrayList<Account>(
)
var gson = GsonBuilder().setPrettyPrinting().create()
val ggson = Gson()
fun writeData(){
FileWriter("accounts.json").use {
ggson.toJson(accounts, it)
}
}
fun readData(){
accounts.clear()
FileReader("accounts.json").use{
var account = gson.fromJson(it, Array<Account>::class.java)
if(account == null){return}
for(i in account){
accounts.add(i)
}
}
}
}
init {
readData()
borderpane {
center {
tableview<Account>{
items = accounts
column("Name", Account::name)
column("Login", Account::login)
column("Password", Account::password)
contextMenu = ContextMenu().apply{
menuitem("Delete"){
selectedItem?.apply{// HERE IS WHERE THE ITEM DELETE CODE SHOULD BE}
}
}
}
}
bottom{
button("Add account").setOnAction{
replaceWith(AddView::class, ViewTransition.SlideIn)
}
}
}
}
}
Thanks!
To clarify #Martacus's answer, in your case you only need to replace // HERE IS WHERE THE ITEM DELETE CODE SHOULD BE with accounts.remove(this) and you're in business.
You could also replace the line
selectedItem?.apply{ accounts.remove(this) }
with
selectedItem?.let{ accounts.remove(it) }
From my experience, let is more common than apply when you are just using a value instead of setting up a receiver.
Note that the process will be different if the accounts list is constructed asynchronously and copied in, which is the default behavior of asyncItems { accounts }.
selectedItem is the item you have selected/rightclicked.
Then you can use arraylist.remove(selectedItem)

Default Button - Vb.NET

I have a button that I want to make default, but without the border thing around the button. Is this possible to do?
Thanks.
The visual cue comes as standard if you set the default button. You could, however, do something with key-preview, capturing carriage-return and performing the required action(s) necessary. To give a C# example (same concepts apply to VB.NET):
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Button btn1, btn2;
using(Form form = new Form {
Controls = {
(btn1 = new Button { Dock = DockStyle.Bottom, Text = "Button 1"}),
(btn2 = new Button { Dock = DockStyle.Bottom, Text = "Button 2"}),
new TextBox { Dock = DockStyle.Fill, Text = "just text"}
}
})
{
btn1.Click += delegate {form.Text = "button 1 clicked";};
btn2.Click += delegate {form.Text = "button 2 clicked";};
form.KeyPreview = true;
form.KeyDown += (sender, args) =>
{
if (args.KeyCode == Keys.Return) btn1.PerformClick();
};
Application.Run(form);
}
}