• I want to extend the Graphics class and be able to use the same "method" names, but extend them. I'd like to do this by creating my own Graphics2 class that inherits from Graphics.

    Problem: How do I create a new Object derived from Graphics2 that's connected to the hardware display, like the built-in LCD object?

    This is the code I found in the source that I'm pretty sure is setting up the LCD var:

    void jswrap_graphics_init() {
    [#ifdef](https://forum.espruino.com/sear­ch/?q=%23ifdef) USE_LCD_FSMC
      JsVar *parent = jspNewObject("LCD", "Graphics");
      if (parent) {
        JsVar *parentObj = jsvSkipName(parent);
        JsGraphics gfx;
        graphicsStructInit(&gfx);
        gfx.data.type = JSGRAPHICSTYPE_FSMC;
        gfx.graphicsVar = parentObj;
        gfx.data.width = 320;
        gfx.data.height = 240;
        gfx.data.bpp = 16;
        lcdInit_FSMC(&gfx);
        lcdSetCallbacks_FSMC(&gfx);
        graphicsSplash(&gfx);
        graphicsSetVar(&gfx);
        jsvUnLock2(parentObj, parent);
      }
    [#endif](https://forum.espruino.com/sear­ch/?q=%23endif)
    }
    

    Pretty straightforward -- if I was coding in C!

    Is there a way to accomplish the same thing in the Javascript interpreter with standard Espruino interfaces/classes, that would be great!

  • I can't think of an easy way. Any reason you can't just add your functions to Graphics? If you want to change what a function does, just overwrite it... and if you want to use the old one, copy it to a new name first.

  • If I grok what you're suggesting, it won't work because Graphics is native code. There is no Javascript access to the prototype object and its properties (in particular, all the functions like fillRect, for example).

    So, I CAN'T do something like:

    LCD.oldProto = Graphics.prototype;
    Graphics.prototype.fillRect = function() {
      if (arguments.length > 4) this.setColor(arguments.slice[-1]);
       this.oldProto.fillRect.apply(this,argume­nts.slice(0,4)); <== this fails -- oldProto is undefined
    }
    

    What does work is creating a new "method" with a different name (fillRect2), which works fine since there's no name collision. However, I then have to deliberately code with that name, which makes the code dependent on having my extensions to Graphics loaded.

    It's not really a big deal... I'm not working on this for a particular project ATM. Rather, I'm working on developing that GUI module for use on the MiniSTM32 with 3.2" display and touchscreen. Developing this mostly out of interest and fun, plan to share with community and use in the future some time.

    I don't have a "real" project for that hardware right now -- just playing.

  • You might not be able to totally rename the prototype, but you should be able to do:

    Graphics. prototype.fillRect2 = Graphics. prototype.fillRect;
    Graphics. prototype.fillRect = ...;
    
  • @dwallersv, even if you would have access to the prototype, the code is not working as intended, because line 2 overwrites the fillRect() of the 'original' prototype you tried to 'save' in line 1. Line 1 does not make a deep-copy... it only creates a 2nd reference to the prototype object...

    Given only this small snippet and no other context, it is not clear to me what this is referencing at runtime...

  • @allObjects: In a prototype function 'this' will reference the particular instance of an object created with the 'new' keyword -- that's my understanding :-)

    @Gordon: Unfortunately, trying to save the function object in a different reference doesn't work -- the native compiled code doesn't expose the symbols, so not even the prototype object referenced by the Graphics.prototype property isn't exposed.

    Don't think this can be done without compiling the Graphics "class" with more information -- maybe debug symbols or something.

    Don't waste any more time on this guys (other than your own curiosity). It's not important to what I'm doing. Thanks!

  • @allObjects: brain ignored this for some reason, must be my advancing age at 54 :-)

    Yes, what you say about overwriting prototype above is correct. I tried that as an alternative to what Gordon suggest -- having tried it an found the function in property fillRect inaccessible -- hoping the prototype object was accessible instead (it's not either). Of course, IF that would work, there's the entire problem of shallow vs. deep copy, etc.

    If the proto object WAS accessible, I was going to then deal with the copy issue (there are ways to make that copy, as I'm sure you're aware -- you're far more experienced with this stuff than I am :-))

  • No worries... 2^3 years 'ahead' of you... so there is some good to that... and hope... ;-) LOOOOL - just no new tricks... (definition of 'ahead' varies with mileage...)

    Was looking at the C... and I wonder why it is not working. Anyway. The Pen idea is a smart one... because it goes back to 'Logo'... the walking (triangle) tortoise / turtle doing some painting with its tail in the sand...

    There is just nothing that can beat a good metaphor.

  • If you have a singleton... and the mapping of the internal/native to the JS object, prototype is questionable... That's why I asked for a bit more code that would show that there was a new on a constructor (class) function that actually establishes the prototype connectivity.

    What I'm confused myself is that not even the Object.prototype was there for you, because creating literally a blank/empty object (in JavaScript with { }) should get at least that. Obviously, with an instance, and more so a literally created singleton, it may be a bit more tricky. The prototype property (prototype object) is attached to the constructor function... getting it from an instance - like the created singleton- it goes this way: Object.getPrototypeOf(instance);. Give it a shot.

    var LCD = { ... };
    console.log(LCD.prototype); // <-- undefined
    var lcdProtoType = Object.getPrototypeOf(LCD);
    console.log(typeof LCD); // <-- "object"
    console.log(lcdProtoType); // <-- Object {}
    

    In other words, it is only an instance of Object that can have instance related methods and properties added... For extending them, save them in an extra variable and override the original one. What you for sure do not want is extend the original Object.prototype with graphics related functions.

    Graphics.fillRectOrig = Graphics.fillRect;
    Graphics.fillRect = function() {
      if (arguments.length <= 4) {
         this.fillRectOrig.apply(this,arguments);­
      } else {
         // your code...
      }
    };
    

    PS: not much validated yet... and I could look way more older than in reality... ;-)

    Last but not least: in Espruino, the term 'Class' is used a bit liberally... especially when coming from Smalltalk, where Classes are first class objects (instances) as well... the class Class is actually a class and creating of new classes is done by saying something like 'Class new'. In Espruino a function library - a singleton from an o-o point of view - is also called a class - and can have state (variable) and behavior (function/method) properties. In other o-o languages they would be called static methods. Anyway, JavaScript is a unique 0-o implementation all together.

  • Its allways funny to listen to these young guys.
    okay only 2^1 years ahead of allObjects ;-))

  • @allObjects: Yeah, "class" in Javascript is a poor bastard of the real thing. My history is doing a log of Javascript about 10-15 years ago, then none for a decade and in that time doing a lot of Java (Android) up to the present, then getting back on the Javascript bandwagon in the last few weeks as I found and got into Espruino.

    So I AM mapping a lot of concepts from Java to Javascript, and learning about the "object model" -- really the prototype inheritance chain.

    A lot has happened with JS in that last 10 years... :-)

  • in Espruino, the term 'Class' is used a bit liberally...

    This was less geared towards JavaScript but more so towards Espruino's unique implementation and documentation / reference.

    Since JavaScript - in its heart / original form - is prototype based, there is no notion of class in the strict way. This creates some troubles - @dwallersv refers to that with *"class" in Javascript is a poor bastard of the real thing - but on the other side allows dynamics that no other (major oo) language offer: the overwriting of the prototype's behavior / function implementation for a particular instance. This has - of course - its consequences as well, especially in (memory) resource constraint environments - but consciously used and over time even variable applied - it is really great. With Espruino 1v86's new ability to set the prototype, literally created objects - especially singletons - do not need to have the typical constructor... (@Gordon: thanks!).

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

Create new connection to HYMiniSTM32 display (NOT the built-in 'LCD' object)

Posted by Avatar for dwallersv @dwallersv

Actions