[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: First mock up of new text UI



Yeah that looks like something I had in mind, did you do this using some code or text editor?

I actually have some prototype code we might use for screen flow (attached). It wont be probably too hard to come up with some "widgets".


Martin

----- Original Message -----
> I spent today thinking through text installs in newui.  While I
> believe
> that text installs should have minimalistic configuration options, I
> also believe that the little it has should follow the same sort of
> idea
> as the hub/spoke design of newui.  Another requirement of text mode
> is
> that the same UI work across all text interfaces (real tty, serial,
> ssh,
> s390 x3270 shell, etc...), targeting the lowest common platform.  For
> systems like s390x that means no curses, no fancy screen widgets,
> just
> dumb text printed on a somewhat narrow screen with no scrolling
> capability.
> 
> What I've done is a hacky mock up of how a text install would
> progress.
>   Some of these config options might go away (like lang/keymap since
>   we
> have good command line argument options for these).  The idea is the
> same as newui.  A hub from which configuration can be done in any
> order,
> but also with some items that are required to be completed.  Of note,
> I
> brought back the root password selection because with text mode you
> only
> get @minimal, and thus no firstboot.  We don't want people to have to
> root their machines just to get a password set.  This is pretty much
> the
> cmdline UI slightly re-designed.
> 
> You'll find a series of screen shots at
> http://jkeating.fedorapeople.org/textui/  Walk through them as
> numbered
> (yes I'm missing a 2-...).
> 
> I have no idea yet if we can handle many choice screens like lang and
> keyboard.  Timezone data can be broken down much how tzselect does
> it.
> 
> Feedback would be appreciated!
> 
> --
> Jesse Keating
> Fedora -- FreedomĀ² is a feature!
> 
> _______________________________________________
> Anaconda-devel-list mailing list
> Anaconda-devel-list redhat com
> https://www.redhat.com/mailman/listinfo/anaconda-devel-list
> 
class ExitMainLoop(Exception):
    pass

class App(object):
    def __init__(self, title):
        self._header = title
        self._spacer = "\n".join(2*[80*"="])

        # screen stack contains triplets
        #  UIScreen to show
        #  arguments for it's show method
        #  value indicating whether new mainloop is needed - None = do nothing, True = execute, False = already running, exit when window closes
        self._screens = []

    def switch_screen(self, ui, args = None):
        """Schedules a screen to replace the current one."""
        self._screens.pop()
        self._screens.append((ui, args, None))
        self.redraw()

    def switch_screen_with_return(self, ui, args = None):
        """Schedules a screen to show, but keeps the current one in stack to return to, when the new one is closed."""
        self._screens.append((ui, args, None))
        self.redraw()

    def switch_screen_modal(self, ui, args = None):
        """Starts a new screen right away, so the caller can collect data back. When the new screen is closed, the caller is redisplayed."""
        self._screens.append((ui, args, True))
        self.redraw()

    def schedule_screen(self, ui, args = None):
        """Add screen to the bottom of the stack."""
        self._screens.insert(0, (ui, args, False))

    def close_screen(self, scr = None):
        oldscr, oldattr, oldloop = self._screens.pop()
        if scr is not None:
            assert oldscr == scr

        # we are in modal window, end it's loop
        assert oldloop != True # this cannot happen, if we are closing the window, the loop must be running or not there
        if oldloop == False:
            raise ExitMainLoop()

        if self._screens:
            self.redraw()
        else:
            raise ExitMainLoop()

    def _do_redraw(self):
        """Draws the current screen and returns True if user input is requested.
           If modal screen is requested, starts a new loop and initiates redraw after it ends."""
        if not self._screens:
            raise ExitMainLoop()

        screen, args, newloop = self._screens[-1]
        input_needed = screen.show(args)

        if newloop == True:
            self._screens.pop()
            self._screens.append((screen, args, False))
            self.run()
            self.redraw()
            input_needed = False # we have to skip input once, to redisplay the screen first

        return input_needed

    def run(self):
        self._redraw = True
        last_screen = None
        while self._screens:
            try:
                if self._redraw or self._last_screen != self._screens[-1]:
                    if not self._do_redraw():
                        continue

                last_screen = self._screens[-1]
                error_counter = 0

                c = raw_input("\tPlease make your choice from above: ")
                if not self.input(c):
                    error_counter += 1

                if error_counter >= 5:
                    self.redraw()

                if self._redraw:
                    print self._spacer
            except ExitMainLoop:
                break

    def input(self, key):
        """Method called to process unhandled input key presses."""
        if self._screens:
            key = self._screens[-1][0].input(key)
            if key is None:
                return True

        if self._screens and key == 'quit':
            self.close_screen()
            return True

    def redraw(self):
        self._redraw = True

    @property
    def header(self):
        return self._header

    @property
    def store(self):
        return self._store


class UIScreen(object):
    def __init__(self, app, store):
        self._app = app
        self._store = store

    def show(self, args = None):
        """Method which displays the screen. If user input is requested, return True."""
        pass

    def input(self, key):
        """Method called to process input. If the input is not handled here, return it."""
        return key

    @property
    def store(self):
        return self._store

    @property
    def app(self):
        return self._app

    def close(self):
        self.app.close_screen(self)

class HelloWorld(UIScreen):
    def show(self, args = None):
        print "Hello World"
        return True

if __name__ == "__main__":
    a = App("Hello World")
    s = HelloWorld(a, None)
    a.schedule_screen(s)
    a.run()

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]