GithubHelp home page GithubHelp logo

luigi's People

Contributors

airstruck avatar lukc avatar ndarilek avatar poke1024 avatar rm-code avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

luigi's Issues

Can't get LUIGI buttons to get pressed by keys under LÖVE2d 0.10.2

Hello airstruck,

I'm new to LÖVE2d and testing various GUIs, among them is LUIGI. It works OK for my needs, except I can't get it to respond to keypress.

I built a simple layout with 4 buttons as the only active controls, it also has two panels to hold the buttons, and a status bar. I declared the "key" attribute on the buttons, but they never respond when I press the corresponding keys.

I suspect this is an issue with intercepting the keypressed and keyreleased events, but I can't get a clue on the example. Also, there is a "Backend" object in the example, that is not documented, and whose role is unclear. I'm searching also in that direction, but to no avail for now.

Thanks in advance for any answer and documentation update on the topic.

Benoît 'Mutos' Robin

Make context menus less of a hack

Context menus created with the context attribute work by adding a menu child to a widget. This causes problems that need to be worked around elsewhere; for example stepper looks for context menu children and gives them special treatment. Context menus should be handled without modifying the widget's children.

Updating text component of a panel doesn't update the text

I have a panel that I'm using for a a dialog box, but I seem to be unable to get the text component of it to update correctly.

Here's the panel I create:

local dialogOpts = {
  type       = 'panel',
  text       = 'Node information dialog box\nShould have a line break in it, but who knows?',
  width      = 350,
  height     = 150,
  wrap       = true,
  background = {200, 200, 200, 240},
  outline    = {255, 255, 255, 255},
}

local panel = Layout(dialogOpts)

Once I've caled panel:show(), however, I can't seem to update the text. Even if I call panel:hide(), then change the text, and call show() again.

Edit: To be more specific, I'm attempting to update the text as follows:

panel:hide()
panel.text = "new text"
panel:show()

Misc. text widget improvements

Nothing major, just some additional polish.

  • Expose some internal functions, esp. functions for manipulating selection range.
  • Handle Del key (remove text in selection range or character to right of collapsed range).
  • Handle CtrlA combo (select whole line).
  • Let double click select whole word under the cursor (up to 2 words if word separator was clicked).
    • Dragging extends selection range one word at a time.
    • A third click (triple click) selects the whole line.

Keyboard word selection:

  • Ctrl moves caret to the beginning of the word on its left.
  • Ctrl moves caret to the end of the word on its right.
  • CtrlShift moves end of selection range to the beginning of the word on its left.
  • CtrlShift moves end of selection range to the end of the word on its right.

Finalize 0.1.0 release candidate

Need to address #2 and #3, update API docs, and write some supporting documentation (examples/tutorials) for 0.1.0 RC.

What else needs to get done before this project is formally announced?

Separate themes from "engines."

Themes are doing too much work, they should be more accessible to designers. Move all function-attributes and some default attributes into engines. Expose most hard-coded values as engine parameters, with current values as defaults. Provide a default engine. Themes should be able to load the engine of their choice, or fall back to the default.

Crash in text widget when selection range extending past EOT is modified

For example, if textWidget.value is "foobar" and the user selects the whole thing (from left to right), then when textWidget.value is set to "foo" (programatically, not by the user), the end of the selection range will extend past the end of the text. If the user hits the left arrow key at this point, an error is thrown.

Either the selection range should never be allowed to extend past EOT (clamp it in onChange), or it should be clamped to the text length when modifying it (clamp it in a bunch of internal functions).

Scrolling improvements

  • Horizontal scrolling (use shift + vertical wheel or horizontal wheel).
  • Let text and icon affect content width/height, and scroll them.
  • Floating scroll bar overlays that appear on hover (maybe).

Improve default mouse event handlers

  • Things like press event handlers should check for primary mouse button, and do nothing if a different mouse button was used. Be sure to still honor press events generated from keyboard accelerators, though.
  • Layouts should eat any wheel events that hit them.
  • Widgets could have a context attribute, containing some menu items. Default behavior for right mouse button would be showing the context menu.
  • Default behavior for middle mouse button could be free scrolling (see also #3) Probably not going to do this unless someone wants it.

Support CJK IME input

See love's textedited event, which is totally undocumented. The attached code is probably the most complete example of its usage that exists. SDL backend will be exactly the same, since love's functions don't do much of anything extra.

Compose events are used for some other cases that aren't CJK as well, but I think only CJK languages use candidate lists.

Love 0.9.2 doesn't actually include everything needed for proper IME support unless you FFI in l.k.setTextInput with additional arguments and update SDL.

(the unabridged version of the following code is here. You may want to look at draw(), and you'll want to ensure that start_editing is called every time the contents change)

-- 0.9 compat. Only *really* works if you've updated SDL, though.
-- function console.textedit(...)
--  return console.textedited(...)
-- end

-- CJK IME's need to know where the cursor is in the window and the size of the
-- text box in order to function properly.
-- 
-- All code tested with Mozc on Windows and Linux.
-- Pretend this is whatever code is needed to get the text cursor position in luigi instead of this console...
local function get_position()
    local prefix = console.ps .. " "
    local x = console.x + console.margin + console.font:getWidth(prefix)
    local y = console.y + console.h + (console.lineHeight - console.fontSize) / 2 -1
    local h = console.font:getHeight()
    local text_l = utf8.sub(console.input, 1, console.cursor)
    local text_r = utf8.sub(console.input, console.cursor+1, -1)
    local pos = x + console.font:getWidth(text_l)
    local w = console.w - x - 3
    return pos, y, w, h
end

local function start_editing()
    local x, y, w, h = get_position()
    love.keyboard.setTextInput(console.visible, x, y, w, h)
    love.keyboard.setKeyRepeat(true)
end

local function stop_editing()
    console.editBuffer = nil
    love.keyboard.setTextInput(false)
    love.keyboard.setKeyRepeat(false)
end

-- alias so it's a little more clear why we're calling start() so much.
local update_ime = start_editing

-- You receive this event while a string is still being composed, so it's up to
-- you to display it properly as this happens.
-- "Properly" meaning you should draw a highlighted box with the contents of
-- editbuffer wherever the text cursor is (so you'll need to do some measuring
-- and temporarily insert characters into your display text)
function console.textedited(t, s, l)
    if not console.visible then
        return
    end
    if t == "" then
        console.editBuffer = nil
    else
        console.editBuffer = { text = t, sel = s }
    end
    update_ime()
end

function console.focus(f)
    if not console.visible then
        return
    end
    if f then
        -- Work around for Windows' stupidity.
        stop_editing()
        start_editing()
    else
        stop_editing()
    end
end

-- Note: You only receive this event when the input has been finalized!
function console.textinput(t)
    if t ~= console._KEY_TOGGLE and console.visible then
        local text_l = utf8.sub(console.input, 1, console.cursor)
        local text_r = utf8.sub(console.input, console.cursor+1, -1)
        console.input = text_l .. t .. text_r
        console.cursor = console.cursor + utf8.len(t)
        update_ime()
        return true
    end
    return false
end

Adding buttons to a scroll list

Quick question. I am working on a UI which has a scrollable list of buttons:

screenshot 2016-01-28 23 16 33

Basically new items should be added to the list when the user drags a folder onto the love window. What's the best way to do this (is it possible at all)?

Figure out desired default behavior for 'enter' key

Currently presses the focused widget (has different behavior in text widgets; it will probably change).

Maybe introduce a new attribute that tells a single button (per layout) to catch all 'enter' key presses. If present, pressing 'enter' presses that button, otherwise, it presses the focused widget (space bar always presses the focused widget).

Document!

Current document is hard to understand. It has no example and yet not complete. e.g. no style field enum explanation

Typing long text hides the cursor and some characters

When typing a text longer than the edit box's width, the last character is displayed partially and the cursor disappears. The look is consistent with the control's boundary box being used for calculations rather than just the inner edit box, similarly to vrld/suit#27 (but I haven't looked at the code). [EDIT: Actually, it is more consistent with being always exactly 1 character behind. It is not a fixed width, as can be shown by entering series of MmMm and ilil]

There are other issues that I'm not sure if they are part of the same issue or not. When the input box is full, pressing the Home/End keys does not seem to make the new cursor position visible. It goes back to normal if the right cursor is pressed after the End key, or if the left cursor is pressed after the Home key.

Text widget should not trap any keypresses it doesn't use.

For example, if another widget has a shortcut of 'z', pressing 'z' in the text widget should type a 'z' into the widget and not activate the other widget (current behavior as of latest commit). But, if another widget has a shortcut of 'escape' the text widget shouldn't trap this, since the text widget doesn't use that key.

In other words, keypresses not associated with text input should be allowed to propagate (unless the text widget has special handling for them, like 'ctrl-c').

From https://wiki.libsdl.org/CategoryKeyboard

SDL_Keycode values are mapped to the current layout of the keyboard and correlate to an SDL_Scancode. Values of this type are used to represent key symbols in the key.keysym.sym field of the SDL_Event structure, among other places. The values in the SDL_Keycode enumeration are based on Unicode values representing the unmodified character that would be generated by pressing the key, or the scancode value with the high bit set (bitwise ORed with 0x40000000) for those keys that do not generate characters. Keycode constants use the symbol name (lowercased for letters) prefixed with SDLK_ (eg: SDLK_SPACE).

Under the SDL backend, we should be able to test for that high bit and let the event propagate if it's present, or if any modifiers keys besides 'shift' were pressed. Not sure whether it's possible to test for that high bit under Love, or if a workaround exists.

Rework special values for width/height

  • Change 'auto' to 'shrink'; shrinks to fit contents.
  • Add 'expand' and treat it like false, expands into available space.
  • Should be able to shrink to fit text/icon contents, see #19.
  • Use 'shrink' as default value for some widgets, like buttons.

Clean up text/icon mess

If a widget has both text and icon, positioning everything properly is complicated. The Text object is currently created by Painter when rendering, but this causes problems when we need to get the text object before rendering (for example when determining a widget's "internal height"). If icon didn't have to be taken into account when creating the Text object, a Widget:getText method would be much easier to manage.

The current system is nice because we can do this:

{ type = 'button', icon = 'save.png', text = 'Save' }

The new system could simply draw the text in front of the icon (so icon and text aren't really meant to be used on the same widget). Creating the same button might look like this now:

{ type = 'button',
    { icon = 'save.png' },
    { text = 'Save' }
}

Of course, button type widgets could do what menu items do, and create their own children based on their attributes (so the current syntax would still work). This adds complexity for individual widget types, but removes complexity from Widget and Painter.

Or, we can go the other direction, bite the bullet and move all the positioning stuff from Painter into Widget.

Another possibility would be changing the icon and text attributes to always create new children, and have dedicated types for those widgets. So the button could be written either way:

{ type = 'button', icon = 'save.png', text = 'Save' }
-- or
{ type = 'button', { image = 'save.png' }, 'Save' }

Clear state

How do I destroy the UI correctly (e.g. when I switch to a different state)?

When I just use ui:hide() the UI still seems to grab button press events etc. when I'm in a different state.

Enable key repeat for text input controls

Key repeat in an input control does not work for some keys, notably for backspace and arrows.

It should probably be handled by preserving the user-set state of key repeat when focus goes elsewhere.

How to integrate the layout with love2d?

I want to implement my options dialog in my game with using luigi. Here is what I have:

local Layout = require("luigi.layout")


local Options = {}
Options.__index = Options


function Options.new(quit_callback)
    local self = setmetatable({}, Options)
    self.__quit = quit_callback
    self.layout = Layout(require("layouts.options"))
    return self
end

function Options:keypressed(key)
    if key == "escape" then
        self.layout:hide()
        self:__quit()
    end
end

function Options:draw()
    self.layout:show()
end

return Options

And the layout.options is the copy of example/layout/main.lua file. Everything works fine (it shows) then I call "draw" of Options object but I don't see any way to hide it. I want to be able to hide it by pressing escape as you can see in the Options:keypressed method.

P.S. If you are interested in my keypressed, draw methods - they are simply a delegates of love.keypressed, love.draw and other functions; I use custom stacked-view widget which passes it's top value to the love and it's top object's functions are called.

Can't enter a 'z' on the input box

I can't enter the letter 'z' on the input box. When doing so, it presses a button instead and the input box loses focus.

Happens with both love2d and luajit+SDL.

Add 'window' widget type

This widget can be used as the root widget of a layout to manage properties of the window.

  • Attribute maximized -> SDL_MaximizeWindow / SDL_RestoreWindow
  • Attribute minimized -> SDL_MinimizeWindow / SDL_RestoreWindow
  • Attribute borderless -> SDL_SetWindowBordered
  • Attribute fullscreen -> SDL_SetWindowFullscreen
  • Attribute grab -> SDL_SetWindowGrab (will it work with Love?)
  • Attribute icon (override) -> SDL_SetWindowIcon
  • Attribute maxwidth/maxheight -> SDL_SetWindowMaximumSize
  • Attribute minwidth/minheight (override) -> SDL_SetWindowMinimumSize
  • Attribute top/left (override) -> SDL_SetWindowPosition
  • Attribute width/height (override) -> SDL_SetWindowSize
  • Attribute title -> SDL_SetWindowTitle

Centering widgets within a layout

I'm trying to figure out how to properly center child widgets within a layout? Currently I have three buttons, within a layout, the flow is set to x. I would like to 'middle center' those buttons within the full size of the layout (which is the window size).

I don't see any examples of this and it seems align only changes text and icons not widgets.

Here's a sample of the code:

local character_select = Layout {
  id = 'characterSelect',
  style = 'character_select_screen',
   {
    type = 'button',
    id = 'btnWarrior',
    text = 'Warrior',
    width = 100,
    height = 32,
    style = 'chararcter_button'
  },
  {
   type = 'button',
   id = 'btnMage',
   text = 'Mage',
   width = 100,
   height = 32,
   style = 'chararcter_button'
 },
 {
    type = 'button',
    id = 'btnRanger',
    text = 'Ranger',
    width = 100,
    height = 32,
    style = 'chararcter_button'
  }
};

local character_select_style = {
  character_select_screen = {
    flow = 'x',    
  },
  chararcter_button = {
    margin = 5,
    align = 'center middle'
  }
}

character_select:setStyle(character_select_style);

Text input crashes on non-ASCII characters with the SDL backend

Steps to reproduce:

  • Run the example with the SDL backend.
  • Select the text input area to give it focus.
  • Press something like “é”.
  • Profit.
luajit: ./luigi/widget/text.lua:340: attempt to get length of local 'key' (a nil value)
stack traceback:
        ./luigi/widget/text.lua:340: in function 'isKeyTextInput'
        ./luigi/widget/text.lua:401: in function 'func'
        ./luigi/hooker.lua:79: in function 'callbacks'
        ./luigi/event.lua:16: in function 'emit'
        ./luigi/widget.lua:288: in function 'bubbleEvent'
        ./luigi/input.lua:25: in function 'func'
        ./luigi/hooker.lua:79: in function 'keypressed'
        ./luigi/backend/ffisdl.lua:89: in function 'run'
        main.lua:108: in main chunk
        [C]: at 0x55729b56e580

I noticed I had to uncomment the Backend.run() line. I’m not sure if additional precautions should be taken when working with luigi and the SDL.

Tab key failing

The fix for issue #37 broke the tab key from a text widget for me.

I think that the problem is a confusion on what the return type and value of the event should be, because this fixed it for me:

diff --git a/luigi/widget/text.lua b/luigi/widget/text.lua
index 23813f1..5d3482c 100644
--- a/luigi/widget/text.lua
+++ b/luigi/widget/text.lua
@@ -381,9 +381,9 @@ This color is used to indicate the selected range of text.
         local act = self.keyActions[event.key]
         if act then
             local result = act()
-            if result then return true end
+            if result then return end
         end
-        return false
+        return true
     end)

     self:onDisplay(function (event)

By type I mean that Event:emit checks explicitly for nil:

    if result ~= nil then return result end

Make shortcut attribute cross-platform friendly?

Brainstorming ideas for making the shortcut attribute make more sense across platforms.

Consider this example:

{ type = 'button', text = 'Save', shortcut = 'ctrl-s' }

This is fine on Windows/Linux, but Mac users will want command-s as the shortcut for saving things. Possible solution (this won't actually work yet; shortcuts don't recognize "gui" as a modifier key yet):

{ type = 'button', text = 'Save', shortcut = { 'ctrl-s', 'gui-s' } }

Now Mac users can press command-s, but they can also press ctrl-s, and Windows/Linux users can press win-s. Only the appropriate shortcut for the user's platform should work.

Another idea:

{ type = 'button', text = 'Save', shortcut = { 'ctrl-s', 'command-s' } }

The command- modifier would only be relevant on Mac, and would never be triggered elsewhere. Similarly, option- could be used for the alt key, but only on a Mac. Problem is, ctrl-s still works on Mac, but shouldn't; we'd need something to call the ctrl key that only applies to non-Mac.

And another idea:

{ type = 'button', text = 'Save', shortcut = 'c-s' }

Here, c-s can mean command on Mac and ctrl elsewhere. This only solves a subset of the problem, but it's probably a large subset and it's a reasonably clean solution.

Current behavior is ctrl- shortcuts really means either ctrl or gui key is pressed, regardless of platform. This should probably change.

Related: #25

Setting default states for radio buttons

Is it possible to assign default states to radio buttons? Let's say I want to create an options screen where the user can select a few things:
screenshot 2016-01-31 12 32 06

I'd store these settings in a file on the user's system and want to reload them next time the program is started. How would I load default states for the selected buttons?

Link slider to panel scroll

I want to create at run time a panel with a variable list of buttons (or labels). I'm aware that I can scroll using the mouse wheel, but I want to do it using a slider. scrollBy function works, but I can't figure how to synchronize scrolling and slider position.

Formalize 'group' attribute

  • The group attribute only exists for radio type widgets; support it everywhere (at least menu items and buttons should be toggle-able somehow).
  • Possibly create pseudo-widget from group, so that things like layout.myGroup.value and layout.myGroup.onPress(...) will work.

Usage for custom framework with letterboxing

I'd like to use LUIGI for my game, but it uses framework which has letterboxing, so it has these restrictions:

  • No call should be made to love.graphics.reset and love.graphics.origin. Additionally, graphics state must be balanced!

  • love.mousepressed, love.mousereleased, love.mousemoved, love.<more handles> shouldn't be overridden. It's substitute is available, and additionally for mouse/touch events, handles the coordinates because letterboxing.

  • Touch events and mouse events are same.

Combobox widget

What's the better way for emulate a combobox? The only thing that occurs to me is to use a menu->menu.items to select an option, and change menu text accordingly.

Enable key repeat in Love

It would be nice if Luigi would allow certain actions to be performed as long as a button is pressed (e.g.: Deleting characters while backspace is pressed, or moving the cursor when the arrow keys are pressed).

All in all it is looking pretty nice already 😊 I would love to implement it in some of my projects asap 👍

Let widget type initializers define custom attribute getter/setters

Attributes are in a static module right now, could either:

  • Make it into a class, store an instance in each widget, or
  • Leave it as a module and let widgets store overrides

Widgets already have an attributes property where some of the attribute values are stored, maybe name the new property attributeDescriptors?

Detect OS X and use appropriate keyboard shortcuts

In general, shortcuts on OS X should use command key instead of control key.

Use love.system.getOS() == 'OS X' in Love and SDL_GetPlatform() == 'Mac OS X' in SDL to figure out if user is on a Mac.

Add a special function like Backend.isControlPressed that detects command key on Mac and control key everywhere else. Is there a better name for this, some word that refers to either a command or control key?

Scrollpanel broken?

Looks like scrolling doesn't work anymore. Tried it both in the example and my own project (I'm only tested my MBP's trackpad so maybe it's just mac-specific?).

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.