Beispiel #1
0
class GridDisplay(object):
    def __init__(self, width, height, font):
        self.width = width
        self.height = height
        self.font = font
        #
        self.internal_cgrid = Cgrid(width=width, height=height)
        (self.cwidth, self.cheight) = font.size('@')
        #
        dim = (width * self.cwidth, height * self.cheight)
        self.screen = pygame.display.set_mode(dim)

    def update(self, cgrid):
        cur_dim = (self.internal_cgrid.width, self.internal_cgrid.height)
        new_dim = (cgrid.width, cgrid.height)
        if cur_dim != new_dim:
            self.internal_cgrid.set_dimensions(width=cgrid.width,
                                               height=cgrid.height)
        updates = []
        o_spots = self.internal_cgrid.spots
        n_spots = cgrid.spots
        for idx, (o_spot, n_spot) in enumerate(zip(o_spots, n_spots)):
            if not o_spot.compare(n_spot):
                updates.append(idx)
                o_spot.mimic(n_spot)
        for idx in updates:
            spot = self.internal_cgrid.spots[idx]
            (font_fg, font_bg) = MAP_CONST_COLOURS_TO_CPAIR[spot.cpair]
            label = self.font.render(spot.c, 1, font_fg, font_bg)
            #
            drop_pixels = self.cwidth * int(idx % self.internal_cgrid.width)
            rest_pixels = self.cheight * int(idx / self.internal_cgrid.width)
            self.screen.blit(label, (drop_pixels, rest_pixels))
        pygame.display.flip()

    def coords_from_mousepos(self, xpos, ypos):
        '''
        From the supplied pixel dimensions, return the drop and rest of the
        selected grid reference.
        '''
        rest = int(xpos / self.cwidth)
        drop = int(ypos / self.cheight)
        return (drop, rest)
class ImplGridConsole:
    def __init__(self):
        self.form = FormGridConsole(self)
        #
        clib = load_clib(self)
        #
        self.api = Ns()
        self.api.set_cc_log = init_ext_fn(None, clib.set_cc_log, [CC_LOG_T])
        self.api.create_screen = init_ext_fn(None, clib.create_screen,
                                             [c_int, c_int])
        self.api.process_windows_events = init_ext_fn(
            c_int, clib.process_windows_events, [])
        self.api.get_next_event = init_ext_fn(None, clib.get_next_event,
                                              [c_uint64_p])
        self.api.set = init_ext_fn(None, clib.set,
                                   [c_int, c_int, c_int, c_int])
        self.api.redraw = init_ext_fn(None, clib.redraw, [])
        self.api.close = init_ext_fn(None, clib.close, [])

    def zero(self, zero_h, cb_grid_console_splat, cb_grid_console_kevent,
             cb_grid_console_mevent, cb_grid_console_closed, engine, width,
             height):
        self.zero_h = zero_h
        self.cb_grid_console_splat = cb_grid_console_splat
        self.cb_grid_console_kevent = cb_grid_console_kevent
        self.cb_grid_console_mevent = cb_grid_console_mevent
        self.cb_grid_console_closed = cb_grid_console_closed
        self.engine = engine
        self.width = width
        self.height = height
        #
        if self.width > 200 or self.height > 100:
            # Note that width and height are by character, not by screen
            # dimension.
            log("Warning. Have seen crashes as screen dimensions become vast.")
            log('width %s %s' % (self.width, type(self.width)))
            log('height %s %s' % (self.height, type(self.height)))
        #
        self.cgrid = Cgrid(width=width, height=height)
        #
        # Emphasis: do not use named parameters for this, or the variable
        # holding the logger will get garbage-collected. You must directly
        # refer to cc_log.
        # xxx rename api to c_api
        self.api.set_cc_log(cc_log)
        #
        log('impl_grid_console w:%s h:%s' % (self.width, self.height))
        self.api.create_screen(self.width, self.height)
        self.api.process_windows_events()
        #
        self.spin_windows_events = self.engine.init_spin(
            construct=SpinWindowsEvents,
            cb_windows_event_quit=self.cb_windows_event_quit,
            cb_windows_event_kevent=self.cb_windows_event_kevent,
            api=self.api)

    def cb_windows_event_quit(self, cs_windows_event_quit):
        zero_h = cs_windows_event_quit.zero_h
        #
        raise SolentQuitException()

    def cb_windows_event_kevent(self, cs_windows_event_kevent):
        zero_h = cs_windows_event_kevent.zero_h
        k = cs_windows_event_kevent.k
        #
        # xxx we will need to do some translation here from windows-style
        # keycodes to solent style. for the moment I am just passing back the
        # raw values.
        keycode = k
        self.form.call_grid_console_kevent(zero_h=self.zero_h, keycode=keycode)

    #
    def send(self, cgrid):
        cur_dim = (self.cgrid.width, self.cgrid.height)
        new_dim = (cgrid.width, cgrid.height)
        if cur_dim != new_dim:
            self.cgrid.set_dimensions(width=cgrid.width, height=cgrid.height)
        updates = []
        o_spots = self.cgrid.spots
        n_spots = cgrid.spots
        for cgrid_idx, (o_spot, n_spot) in enumerate(zip(o_spots, n_spots)):
            if not o_spot.compare(n_spot):
                updates.append(cgrid_idx)
                o_spot.mimic(n_spot)
        log('send')
        for cgrid_idx in updates:
            spot = self.cgrid.spots[cgrid_idx]
            #
            drop = int(cgrid_idx / self.cgrid.width)
            rest = int(cgrid_idx % self.cgrid.width)
            c = ord(spot.c)
            o = 0  # xxx
            log('update %s %s %s %s' % (drop, rest, c, o))
            self.api.set(drop, rest, c, o)
        self.api.redraw()

    def close(self):
        log('close')
        return self.api.close()