Skip to content

Instantly share code, notes, and snippets.

@saikyun
Last active July 19, 2021 10:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save saikyun/fe83077d594082e9dd63f431e1dabac7 to your computer and use it in GitHub Desktop.
Save saikyun/fe83077d594082e9dd63f431e1dabac7 to your computer and use it in GitHub Desktop.

Today I've worked on the layouting of Freja.

Specifically, using tuples and structs, you can now create fabulous designs.

I'm getting ahead of myself though. I should start with the problem, the reason why I started making this very nice system that I will soon tell you about.

Freja has a menu, like any old program. This is how it looks.

The problem, originally, is that when my dear friend sogaiu wanted to add some menu items, the code looked like this:

# ...more terror above

     :edit (let [btns [[i/undo!2 "Undo"]
                       [i/redo! "Redo"]
                       [i/cut! "Cut"]
                       [gb/copy "Copy"]
                       [i/paste! "Paste"]
                       [i/search2 "Search"]
                       #
]]
             [:rec {:rec [(unit 8) ((menu :rec) 3)
                          180 (menu-height (length btns))]
                    :bg 0x3E3E3Eff}
              #   [:button {:pos (urec 10 7)
              #            :on-click |(do (put menu :submenu nil)
              #                          (e/put! state/focus123 :focus frp/text-area)
              #                         (i/undo!2 gb-data))}
              #   "Undo"]

              [:+ {}
               ;(seq [i :range [0 (length btns)]
                      :let [[f s] (btns i)
                            rec (urec 10 (+ 7 (* i 5)))]]
                  (menu-button rec f s))]
              #
]))

# and the dreadful nether below...

As you can imagine, sogaiu was very confused. But he pushed through, and managed to add some more items.

Then he wanted to right align the hotkeys.

😱

I had no good answer for this. First I tried to explain how to "get the width and subtract the width of the hotkey to the yak-yak". But even I couldn't stand reading what I wrote.

I didn't think this was befitting of Freja, an editor that prides herself in being highly usable and easy to modify. To solve this, I needed to come up with a layouting system that was easy to use. Specifically, things like "align this to the right" should be expressable without having to resort to absolute pixels.

It's taken me about one and a half week, but now I have something that is starting to become usable. At least, it solves the problem of aligning things to the right.

So, how does it look now? Lo and behold, this is the code for the new menu! (as of commit [doesn't exist])

# missing code goes here

Oh, there's no real commit? No code? Well, that's because I haven't written the new menu yet. but it's coming! in the meantime, you can check out the new menu's ugly cousin here.

Here's a picture.

And the code for the ugly cousin. I mean, while the ugly cousin might not look so well, the code is surprisingly neat (please let me just revel in it for a bit):

          :file
          [block {}
           [button {:on-press
                    (fn [self ev]
                      (i/open-file (frp/text-area :gb))
                      (e/put! state :menu nil))}
            [grid {:space-between true}
             "Open"
             "Ctrl+O"]]
           [button {:on-press (fn [& _]
                                (i/quit (frp/text-area :gb)))}
            [grid {:space-between true}
             "Quit"
             "Ctrl+Q"]]]

But what does this mean? you say. I mean, I can already hear you say "this is no better! curse this monstrosity!". So, let's take a smaller example first.

[text {:size 40} "imagine this text being pretty big"]

What do you think the above does? Well, it renders text. I'm not here to try to get you to think, I just want you to be amazed at the simplicity of Freja.

Okay, next . I mean, that isn't very interesting. Perhaps we would like something to happen, say, when we click the text?

[button {:on-press (fn [& _] (print "hey, why did you click me?!"))}
  [text {} "Text for the button"]]

Okay, so, now if we render this, and click the text, some other text is printed in the terminal. That's amazing!

Still though, even if we got some interactivity, we don't really have much going on in the long run. Perhaps we could get the respondee to become nicer over time.

(def responses ["<ignored>"
                "i'm not talking to you"
                "sup?"
                "old chap"])

(defonce state @{:love 0})

(defn btn
  [props & _]
  [button {:on-press (fn [& _]
                       (print (responses (props :level)))
                       (e/update state :love inc))}
   [text {} "say hello"]])

Now when we click the button, we get a response (starting out pretty rude) then our love meter increases (and we get nicer responses)! That's amazing. Soon we will have a dating sim!

Speaking of dating sims, I have this hilarious friend, Malin, with whom I recently spoke to -- after not having talked for over 5 years! I managed to get a son in the meantime, so one could really say it's been a lifetime since we last spoke. Either way, we studied game development together, and I always thought she was really good at illustrating and graphic design. So naturally we talk about games we're working on. She mentions that she's making a horse dating sim in the star trek universe! And I was just like "wow, I love how she can say that with a straight face" (which I told her). I really wish I can become as honest with myself as Malin is. I'm working on it! Okay, I'll dare myself: I.. I.. I love katanas! They're so cool! Especially with wavy patterns on the blade and ornations on the guard.

That wasn't too bad, right?

The funny thing is, when I get to play the game, it's actually really wholehearted and cute. you should definitely check it out. Oh right, you can't because it's MVP only. 😎

So, where were we?

Oh, right. We were making a dating sim! Well, not really. This is actually the end of this blog post.

But what was the point? Well, the point is, that now one can express the same things as above, but you don't have to write out numbers (unless you really want to). I guess the examples didn't express this very well -- but that's because this is just my random blog, and I don't have to make any sense. Good bye!

The future?

Next up I have to fix the text rendering, specifically to make it easy to load fonts of different sizes, so the menu looks right and not as the ugly cousin. Then I need to make it so that one can define "grids" which influence the children's sizes. Currently there is support for controlling the spacing (like aligning to the right), but not really for relative widths and whatnot. So that's what I'm thinking about when I'm supposed to spend quality time with my wife. That's actually the reason I wanted to write this blog post in the first place, so that my mind would be a bit relieved before it was time to watch community with my wife!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment