Giter Club home page Giter Club logo

arena-kotlin-extensions's Introduction

Build Status JitPack

Kotlin Extensions for Arena Framework

Arena MVVM Framework

About this repository

This package allows you to use Arena with Kotlin in a more pleasant way.

It provides some extensions that take advantage of Kotlin's functionality, as well as the possibility of extending the classes and high order functions.

Dependency

In your pom.xml, you need to add this to repositories

<repository>
  <id>jitpack.io</id>
  <url>https://jitpack.io</url>
</repository>

And this to dependencies

<dependency>
  <groupId>com.github.unq-ui</groupId>
  <artifactId>arena-kotlin-extensions</artifactId>
  <version>1.4.0</version>
</dependency>

Since Maven version 3.8.1 http repos do not work anymore, and we need to add a few mirrors in order to be able to download the dependencies.

Add a maven.config file in your project (and configure your IDE to use it) with the following contents:

--settings ./.mvn/local-settings.xml

Then add a local-settings.xml file with the following contents:

<settings xmlns="http://maven.apache.org/SETTINGS/1.2.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.2.0 http://maven.apache.org/xsd/settings-1.2.0.xsd">
    <mirrors>
        <mirror>
            <id>uqbar-mirror</id>
            <mirrorOf>uqbar</mirrorOf>
            <name/>
            <url>http://maven.uqbar.org/releases/</url>
            <blocked>false</blocked>
        </mirror>
        <mirror>
            <id>uqbar-wiki.org-releases-mirror</id>
            <mirrorOf>uqbar-wiki.org-releases</mirrorOf>
            <name />
            <url>http://uqbar-wiki.org/mvn/releases</url>
            <blocked>false</blocked>
        </mirror>
        <mirror>
            <id>uqbar-wiki.org-snapshots-mirror</id>
            <mirrorOf>uqbar-wiki.org-snapshots</mirrorOf>
            <name />
            <url>http://uqbar-wiki.org/mvn/snapshots</url>
            <blocked>false</blocked>
        </mirror>
    </mirrors>
</settings>

How to use

Important: You always have to add this import:

import org.uqbar.arena.kotlin.extensions.*

Quick Start

package examples

import java.awt.Color
import org.uqbar.arena.widgets.*
import org.uqbar.arena.windows.MainWindow
import org.uqbar.arena.kotlin.extensions.*
import org.uqbar.commons.model.annotations.Observable

fun main() = ExampleWindow(AppModel(42, Color.YELLOW)).startApplication()

@Observable class AppModel(var number: Int, var bg: Color)

class ExampleWindow(model: AppModel) : MainWindow<AppModel>(model) {
  override fun createContents(mainPanel: Panel) {
    title = "Example"
    Label(mainPanel) with {
      text = "Soy un label"
      bindBackgroundTo("bg")
    }
    TextBox(mainPanel) with {
      bindTo("number")
    }
  }
}

Components

Inputs

Text Boxes
TextBox(mainPanel) with {
  height = 20
  width = 45
  bindTo("textBoxText")
  bindColorTo("blue")
  bindEnabledTo("enabled")
  withFilter { it.inputText.toString().contains("a") }
}

TextBox(mainPanel) with {
  fontSize = 24
  align = "center" // right, left, center
  color = Color.YELLOW
  bgColor = Color.BLUE
  bindTo("textBoxText")
}
Numeric Fields
NumericField(mainPanel) with {
  height = 20
  width = 45
  bindTo("number")
  bindColorTo("blue")
  bindEnabledTo("enabled")
  withDecimals = false  
}

NumericField(mainPanel) with {
  fontSize = 20
  color = Color.WHITE
  bgColor = Color.BLACK
  withDecimals = true
  bindTo("number")
}
Password Fields
PasswordField(mainPanel) with {
  bindTo("password")
  fontSize = 20
}
Text Areas
KeyWordTextArea(mainPanel) with {
  height = 200
  bindTo("textBoxText")
  bindColorTo("blue")
  bindEnabledTo("enabled")
}
Spinners
Spinner(mainPanel) with {
  width = 50
  minValue = 2
  maxValue = 10
}

Labels

Label(mainPanel) with {
  text = "Ejemplo"
  width = 400
  height = 200
  fontSize = 16
  align = "center"
  color = Color.BLUE
  bgColor = Color.CYAN
}

Label(mainPanel) with {
  bindTo("text")
  bindColorTo("blue")
  bindBackgroundTo("orange")
  bindEnabledTo("enabled")
  bindVisibleTo("visible")
}

Options

Selectors
Selector<Item>(mainPanel) with {
  bindItemsTo("items").adaptWithProp<Item>("name")
  bindColorTo("color")
}
Lists
List<Item>(mainPanel) with {
  bindItemsTo("items").adaptWithProp<Item>("name")
  bindSelectedTo("itemSelected")
  bindBackgroundTo("color")
}
Radio Selectors
RadioSelector<Item>(mainPanel) with {
  bindItemsTo("items")
  bindSelectedTo("itemSelected")
}

Check Boxes

CheckBox(it) with {
  bindTo("selected")
  bindEnabledTo("disabled")
  bindBackgroundTo("color")
}

Actions

Buttons
Button(mainPanel) with {
  caption = "Button 1 Blue"
  color = Color.BLUE
  fontSize = 14

Button(mainPanel) with {
  text = "Click Me again" // text is an alias of caption
  color = Color.RED
  setAsDefault()
}

Button(mainPanel) with {
  bindCaptionTo("buttonName")
  onClick { modelObject.inc() }
}
Links
Link(mainPanel) with {
  text = "Click Me!"
  onClick { modelObject.inc() }
}

Link(mainPanel) with {
  caption = "No hago nada!"
}
File Selectors
FileSelector(mainPanel) with {
  title = "Title of the selection window"
  caption = "Seleccionar archivo..."
  path = "/home"                // Path where selection window open by default
  bindTo("storage")             // Where file selected will be saved
  extensions("*.txt", "*.png")  // Extensions allowed
}

FileSelector(mainPanel) with {
  path = "/home"
  setAsDefault()
  bindTo("storage")
  bindCaptionTo("caption")
}

Tables

table<Item>(mainPanel) {
  bindItemsTo("items")
  bindSelectionTo("selected")
  visibleRows = 5
  column {
    title = "ID"
    fixedSize = 30
    bindContentsTo("id")
    bindBackgroundTo("blue")
  }
  column {
    title = "Name"
    weight = 50
    align("center")
    bindContentsTo("name")
  }
  column {
    title = "Description"
    background = Color.BLACK
    align("right")
    bindContentsTo("description")
  }
}

Types of Panels

Panels
Panel(mainPanel) with {
  asVertical()
  width = 250
  Label(it) with {
    text = "Label V1-1"
    width = 200
    height = 75
  }
  Label(it) with { text = "Label V1-2" }
}

Panel(mainPanel) with {
  asHorizontal()
  Label(it) with { text = "Label H1-1" }
  Label(it) with { text = "Label H1-2" }
}

Panel(mainPanel) with {
  asColumns(3)
  Label(it) with { text = "Label C1-1" }
  Label(it) with { text = "Label C1-2" }
  Label(it) with { text = "Label C1-3" }
}
Group Panels
GroupPanel(mainPanel) with {
  title = "Group Panel"
  asHorizontal()
  Label(it) with { text = "Label H1-1" }
  Label(it) with { text = "Label H1-2" }
}

arena-kotlin-extensions's People

Contributors

hurrellt avatar juanmottesi avatar laendoor avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

Forkers

kevinstanleyunq

arena-kotlin-extensions's Issues

Align as an enum

It is easier to interact with an enum than with a string.

fun Control.align(position: String): Control =
  when (position.toLowerCase()) {
    "left" -> this.alignLeft()
    "right" -> this.alignRight()
    "center" -> this.alignCenter()
    else -> this.alignLeft()
}

Something like

fun Control.align(position: Align): Control =
  when (position) {
    Align.left -> this.alignLeft()
    Align.right -> this.alignRight()
    Align.center -> this.alignCenter()
    else -> this.alignLeft()
}

Extender Label en Kotlin como prueba de concepto

Si bien las extensiones de Kotlin son muy versátiles, no se está aprovechando todo el poder de kotlin para generar una sintaxis de arena muchísimo más amena.

Por ejemplo, me gustaría que se pudiese definir un label de esta manera:

Label(mainPanel) {
  text = "Soy un texto libre"
  width = 500
  height = 300
  fontSize = 16
  color = Color.BLUE
  bgColor = Color.CYAN
}

Usando sólo las extensiones no es posible hacer eso porque no se puede generar un nuevo constructor.

Una de las ventajas que tiene Kotlin es que si el último argumento es una función, se pueden evitar los paréntesis. Además es posible "meter" el contexto de ejecución dentro de la función, pudiendo escribir en el bloque como si uno estuvise dentro de la instancia (de hecho lo está).

Para lograr hacer esto sin tener que reescribir todos los componentes, lo que busco hacer es crear una nueva clase Label pero que funcione como Wrapper/Adapter/Bridge, manteniendo como colaborador la instancia Label original. Pero también hago uso de las extensiones para evitar tener que redefinir mucho del comportamiento.

Por ejemplo:

import org.uqbar.arena.widgets.Label as UqLabel
class Label(private val panel: Panel) {
  val content: Label = this
  private val uqbarLabel: UqLabel = UqLabel(this.panel)
  
  var text: String? = null
    set(value) {
      field = value
      value?.let { uqbarLabel.text = it }
    }
  /* ... */
  constructor(panel: Panel, block: Label.(Label) -> Unit) : this(panel) {
    this.block(this)
  }

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.