show dialog from controller - kotlin

I want to show a dialog inside my tornadofx application, but I don't want to create the dialog in the view. I've tried to create a dialog at the controller, but this doesn't seem to work.
This is an working example on how I can create a dialog inside my View
class MainScreenSelect : View("tool") {
override val root = vbox {
dialog("dialog") {
// Code how the dialog looks and how it behaves
}
}
}
My problem is, that I don't want to create my dialog inside my View, I want to create the dialog inside my controller. I assign the Vbox of my View to a variable inside my controller and want to create the dialog inside my controller.
This will be my View then
class MainScreenSelect : View("tool") {
private val controller : Controller by inject()
override val root = vbox {
controller.vbox = this
controller.showDialog()
}
}
The Vbox of the View is assigned to a variable inside the controller and the next line should create a dialog.
My controller will look like this
class ChatScreenController : Controller() {
var vbox : Vbox by singleassign()
fun showDialog(){
vbox.apply{
dialog{} // Here is the error, I can't call dialog at this point, but I can
// call it if I do vbox.apply inside the View
}
}
My problem is, why can't I create the dialog inside my controller? I can create any other elements inside vbox.apply, like another vbox, button... , but no dialog. Where is my error and how can I create a dialog from a controller instead of a view?
edit: I already tried to create a dialog with
Dialog<R>().apply{
//CODE
}
This creates a dialog, but it doesn't lock my mainscreen to force an input and I can't close this window by pressing X(To be honest I didn't really know what I did with the Dialog, but if this is the way to go I'll look into it, how to work with this Dialog)

SOLVED: My mistake was, that I thought 'dialog' belonged to the UI Element vbox, but dialog is related to the View. Changing the variable inside the controller to View instead of an UI Element made it possible to create a dialog for this View.
This is the new Controller
class ChatScreenController : Controller() {
var view : View by singleassign()
fun showDialog(){
view.dialog{
// Code for the Dialog
}
}
The View needs to be changed to assign itself to the variable view inside the controller
class MainScreenSelect : View("tool") {
private val controller : Controller by inject()
override val root = vbox {
controller.view = this#MainScreenSelect
controller.showDialog()
}
}

Related

How to reference a button from different view in Fragment. Kotlin

I want to achieve a simple task. I have an invisible button in one layout and a have a Fragment. When this function is executed I want the button in the other layout to become visible. However this layout with the button is not in the Fragment layout, which means I have to reference that button in the Fragment, but I don't know how to go about that.
This is what Fragment will look like to first time users. The images you see are in a recyclerview which inflates a layout. That layout has the invisible button.
Fragment class
//item subscribed
if (subscribeValueFromPref) {
subscribeAbstract.visibility = View.GONE
// abstractDownload.visibility = View.VISIBLE
} else {
subscribeAbstract.visibility = View.VISIBLE
// abstractDownload.visibility = View.VISIBLE
}
}
When this line of code executed the button in the fragment is gone and the button from the other layout becomes visible. As you can see I put two strokes in front of that code. Once the code has been executed the layout should look like this.
Summary
I want to reference a button in another layout from a fragment class.
Do you even need to communicate between fragments? Your example looks like a single fragment with a subscribe button, and a RecyclerView that contains items which have a button that can be displayed or hidden. You can just make that part of your Adapter's state, like this:
class MyAdapter : RecyclerView.Adapter<ViewHolder>() {
var showDownloadButtons = false
set(value) {
field = value
// call this to update the display (calls onBindViewHolder for items)
notifyDataSetChanged()
}
override fun onBindViewHolder(viewHolder: ViewHolder, position.Int) {
...
// when displaying an item, show or hide the download button as appropriate
viewHolder.downloadButton.visibility = if (showDownloadButtons) VISIBLE else INVISIBLE
}
}
Then in your fragment, when you work out your UI state based on that subscription value, you can just handle your main button and tell the adapter what to display:
if (subscribeValueFromPref) {
subscribeAbstract.visibility = View.GONE
adapter.showDownloadButtons = true
} else {
subscribeAbstract.visibility = View.VISIBLE
adapter.showDownloadButtons = false
}

How to change the fonts of all items on recyclerview runtime

I wanted to change font family of items on a recycler view every time I click a button.
So I coded like below.
rbAritaBuri = view.findViewById(R.id.rb_aritaBuri)
rbCafe24 = view.findViewById(R.id.rb_cafe24SurroundAir)
rbAritaBuri.setOnClickListener {
rv_work_preview.tv_work_content.typeface = Typeface.createFromAsset(requireActivity().assets, "fonts/arita_buri.otf")
}
rbCafe24.setOnClickListener {
rv_work_preview.tv_work_content.typeface = Typeface.createFromAsset(requireActivity().assets, "fonts/cafe24_surround_air.ttf")
}
But it changes only the font family of the first item of the recycler view.
Is there a way to change fonts of them all together runtime? And please tell me why the code I wrote doesn't work right.
Thank you.
If I were in your position, I would:
Put your font changing calls inside of onBindViewHolder(). If you have to, you could put a bool in there like buttonClicked and link its value to your buttons.
Come up with a good way to force a call to onBindViewHolder(). Sometimes notifyDataSetChanged() is enough. But in some cases, you might have to remove the adapter by setting it to null and then reset the adapter to its original value.
Place that logic from step 2 inside of your buttons' onClick()s.
Edit:
What I mean is, create a var inside the class with the most exterior scope, so outside of oncreate().
var textChoice=""
Now use your buttons to change that var.
rbAritaBuri.setOnClickListener {
textChoice="fonts/arita_buri.otf"
}
Now inside your onBindViewHolder(), make the font switch.
when (fontChoice){
"fonts/arita_buri.otf"->{ rv_work_preview.tv_work_content.typeface = Typeface.createFromAsset(requireActivity().assets, "fonts/arita_buri.otf")}
//and so on and so forth for all of your fonts
Now when you want to show the change, call notifyDatasetChanged(). I think maybe the best place to do that would be inside of your buttons. So maybe you'd actually have:
rbAritaBuri.setOnClickListener {
textChoice="fonts/arita_buri.otf"
<The name of your recyclerview adapter>.notifyDatasetChanged()
}
Here is how I solved it, thanks to D. Kupra:
class SampleWorkAdapter(private val context: Context) :
RecyclerView.Adapter<SampleWorkAdapter.ViewHolder>() {
var selectedFont = EditTextActivity.HAMBAK_SNOW
First, I assigned the default font Hambak_snow to selectedFont, type String.
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
...
fun changeFont(font: String) {
CustomFontHelper.setCustomFont(content, font, itemView.context)
} ...
}
Then I wrote a function to be called on onBindViewHolder to change font-family of textview, using custom typeface. https://stackoverflow.com/a/16648457/15096801 This post helped a lot.
override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
...
viewHolder.changeFont(selectedFont)
...
}
Now, replaceFont will be called when the variable selectedFont get changed and adapter.notifyDatasetChanged() is called on an activity, like this:
rbMapoFlowerIsland.setOnClickListener {
sampleWorkAdapter.selectedFont = EditTextActivity.MAPO_FLOWER
sampleWorkAdapter.notifyDataSetChanged()
}

WKWebView's Context menu "Download Image" menu item not responding....

Image download from right click "Context Menu" not responding in the web page loaded in WKWebview. If any body knows help me to identify which delegate method will receive this call or is there any manual implementation needed to get this option work.
App:Mac Application. Language : Objective C. SDK: Xcode
You can intercept context menu items of the WKWebView class by subclassing it and implementing the willOpenMenu method like this:
class MyWebView: WKWebView {
override func willOpenMenu(_ menu: NSMenu, with event: NSEvent) {
for menuItem in menu.items {
if menuItem.identifier?.rawValue == "WKMenuItemIdentifierDownloadImage" ||
menuItem.identifier?.rawValue == "WKMenuItemIdentifierDownloadLinkedFile" {
menuItem.isHidden = true
}
}
}
}

In TornadoFX, how can I separate layouts to different classes and then use them in builder?

For example, I want to have a TabPane, but I want to have tabs each in its separate class. Is there a way to make this work with the builder? I want to do something like this:
tabpane {
MyFirstTab()
MySecondTab()
etc.
}
On a general basis you add the root node from another View with the add command:
add(SomeView::class)
You can also inject a View and add it:
val someView: SomeView by inject()
override val root: borderpane {
center {
add(someView)
}
}
add is the same as doing this += someView. What happens here is that the framework find the root node of the View and appends it to the children property of the parent Node. It also knows about special containers like the BorderPane, so it does the right thing when you add something inside the center builder etc.
The TabPane however, takes Tab instances, which are not nodes. You need to add the tab using the tab builder and assign some content to it. The builders are smart enought to understand that if you do add inside a Tab, it should assign to the content property of the Tab. Therefore you can write:
tab("My First Tab") {
add(MyFirstTab::class)
}
Or if you already have an instance of the content you'd like to assign:
tab("My First Tab") {
add(myFirstTab)
}
The MyFirstTab class must be a View or Fragment.

Eclipse plugin development - How to add Radio buttons in WizardNewFileCreationPage

I am using WizardNewFileCreationPage to create a New File
public void addPages() {
mainPage = new WizardNewFileCreationPage("FILE", getSelection());
mainPage.setTitle("New File");
mainPage.setDescription("Add new file");
addPage(mainPage);
}
I want to add some Radio Buttons to it representing file extensions in this wizard so that users can select one of them as a file extension.
The WizardNewFileCreationPage is not meant to be extended with custom controls. From its JavaDoc:
Subclasses may override
getInitialContents
getNewFileLabel
Subclasses may extend
handleEvent
If you still want to add the radio buttons 'at your own risk', you can try to override createAdvancedControls and append you controls to the parent after calling super.
protected void createAdvancedControls(Composite parent) {
super.createAdvancedControls( parent );
Button radioButton = new Button( parent, SWT.RADIO );
// ...
}
Note that the layout of parent (currently) is a single-columned GridLayout, set the layout data accordingly.