예제 #1
0
struct widget * widget_new_list(struct widget * parent, int x, int y, int width, int height, struct stack * items)
{
  struct widget * rv;
  int scrollbar_width;
  int visible_items;

  {
    struct widget * tmp;

    tmp = widget_new_button(widget_root(), 0, 0, "x");
    visible_items = (height - 2) / widget_height(tmp);
    widget_delete(tmp);

    int item_count;

    item_count = 0;
    for(unsigned int i = 0; i < items->size; i++)
      if(items->data[i] != NULL)
        item_count++;

    if(item_count <= visible_items)
      scrollbar_width = 0;
    else
      scrollbar_width = 20;
  }

  rv = widget_new_child(parent, x, y, width, height);
  widget_set_ulong(rv, "type", WT_LIST);

  struct stack * itemobjs;

  itemobjs = stack_new();
  widget_set_pointer(rv, "items", 'P', itemobjs);

  struct widget * container, * frame;

  container = widget_new_child(rv, 0, 0, width - scrollbar_width, height);
  widget_add_flags(container, WF_CLIPPING);

  frame = widget_new_frame(container, 0, 0, width - scrollbar_width, height);
  frame->z_ = rv->z_;
  widget_delete_flags(frame, WF_CAST_SHADOW | WF_DRAW_BORDERS | WF_BACKGROUND);

  struct widget * prev;

  y = 0;
  prev = NULL;
  for(unsigned int i = 0; i < items->size; i++)
    if(items->data[i] != NULL)
      {
        struct widget * obj;

        obj = widget_new_button(frame, 0, y, items->data[i]);
        stack_push(itemobjs, obj);
        widget_delete_flags(obj, WF_DRAW_BORDERS | WF_ALIGN_CENTER);
        widget_set_ulong(obj, "alpha", 0x80);
        widget_set_width(obj, widget_width(frame));
        widget_set_ulong(obj, "value", i);
        widget_set_widget_pointer(obj, "list_object", rv);
        widget_set_on_release(obj, on_item_release);
        widget_set_on_focus(obj, on_item_focus);
        y += widget_height(obj);

        if(prev != NULL)
          widget_set_navigation_updown(prev, obj);
        prev = obj;
      }
  widget_set_height(frame, y);
  widget_set_widget_pointer(rv, "focus_down_object", prev);

  if(scrollbar_width > 0)
    {
      struct widget * scrollbar, * scrollbar_button;
      int bheight;

      scrollbar = widget_new_frame(rv, width - scrollbar_width, 0, scrollbar_width, height);
      scrollbar->z_ = rv->z_;
      widget_delete_flags(scrollbar, WF_CAST_SHADOW);
      widget_set_on_activate_at(scrollbar, on_scrollbar_clicked);
      widget_set_enabled(scrollbar, true);
      widget_add_flags(scrollbar, WF_FOCUSABLE);
      
      scrollbar_button = widget_new_button(scrollbar, 1, 1, NULL);
      widget_set_width(scrollbar_button, scrollbar_width - 2);
      bheight = 0;
      if(items->size > 0)
        bheight += (height - 2) * visible_items / items->size;
      if(bheight > height - 2)
        bheight = height - 2;
      widget_set_height(scrollbar_button, bheight);
      widget_set_on_activate_at(scrollbar_button, on_scrollbar_button_clicked);
      widget_set_widget_pointer(scrollbar_button, "frame", frame);
      widget_set_widget_pointer(scrollbar, "scrollbar_button", scrollbar_button);
      widget_set_widget_pointer(rv, "scrollbar_button", scrollbar_button);
    }

  return rv;
}
예제 #2
0
void    TileViewer_Update(t_app_tile_viewer *app)
{
    ALLEGRO_BITMAP *bmp = app->box->gfx_buffer;

    // Skip update if not active
    if (!app->active)
        return;

    // If skin has changed, redraw everything
    if (app->box->flags & GUI_BOX_FLAGS_DIRTY_REDRAW_ALL_LAYOUT)
    {
        TileViewer_Layout(app, FALSE);
        app->box->flags &= ~GUI_BOX_FLAGS_DIRTY_REDRAW_ALL_LAYOUT;
        app->dirty = TRUE;
    }

    bool dirty_all = app->dirty || Palette_EmulationDirtyAny;
    bool dirty = dirty_all;

    // Update hovered tile index
    {
        const int mx = app->tiles_display_zone->mouse_x;
        const int my = app->tiles_display_zone->mouse_y;
        // Msg(MSGT_USER, "mx = %d, my = %d", mx, my);
        if (app->tiles_display_zone->mouse_action & WIDGET_MOUSE_ACTION_HOVER)
            app->tile_hovered = ((my / 8) * 16) + mx / 8;
        else
            app->tile_hovered = -1;
    }

    // Compute the tile that is to display in the bottom info line
    int tile_current = (app->tile_hovered != -1) ? app->tile_hovered : app->tile_selected;
    bool tile_current_refresh = /*(tile_current == -1) ? FALSE : */ (((tile_current != app->tile_displayed) || dirty_all || tgfx.Tile_Dirty [tile_current]));
    int tile_current_addr = -1;
	
	const v2i tiles_frame_pos = app->tiles_display_frame.pos;
	const v2i tile_selected_pos = v2i(app->tile_selected_frame.pos.x + 2, app->tile_selected_frame.pos.y + 2);

	int vram_addr_min = 0x0000;
	int vram_addr_size = 0;
	int vram_tile_size = 1;

    // Then redraw all tiles
	ALLEGRO_LOCKED_REGION* locked_region = al_lock_bitmap(app->box->gfx_buffer, ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_READWRITE);
    switch (g_driver->vdp)
    {
    case VDP_SMSGG:
        {
			widget_set_enabled(app->vram_addr_tms9918_scrollbar, false);
			vram_addr_min = 0;
			vram_addr_size = 0x4000;
			vram_tile_size = 32;

            int n = 0;
            const u8 *    nd = &tgfx.Tile_Decoded[0][0];
            const u32 *   palette_host = app->palette ? &Palette_EmulationToHostGui[16] : &Palette_EmulationToHostGui[0];
            for (int y = 0; y != app->tiles_height; y++)
			{
                for (int x = 0; x != app->tiles_width; x++)
                {
                    if (tgfx.Tile_Dirty [n] & TILE_DIRTY_DECODE)
                        Decode_Tile (n);
                    if (dirty_all || tgfx.Tile_Dirty [n])
                    {
                        VDP_Mode4_DrawTile(app->box->gfx_buffer, locked_region, nd, palette_host, tiles_frame_pos.x+(x * 8), tiles_frame_pos.y+(y * 8), 0);
                        tgfx.Tile_Dirty [n] = 0;
                        dirty = TRUE;
                    }
                    if (n == tile_current)
					{
                        tile_current_addr = vram_addr_min + (n * 32);
						VDP_Mode4_DrawTile(app->box->gfx_buffer, locked_region, nd, palette_host, tile_selected_pos.x, tile_selected_pos.y, 0);
					}
                    n ++;
                    nd += 64;
                }
			}
            break;
        }
    case VDP_TMS9918:
        {
			widget_set_enabled(app->vram_addr_tms9918_scrollbar, true);
			vram_addr_min = 0x0000 + app->vram_addr_tms9918_current*0x1000;
			vram_addr_size = 0x1000;
			vram_tile_size = 8;

			const int fg_color = Palette_EmulationToHostGui[app->palette + 1];
            const int bg_color = Palette_EmulationToHostGui[(app->palette != 0) ? 1 : 15];
            const u8 * addr = VRAM + vram_addr_min;
			//VRAM = g_machine.VDP.sg_pattern_gen_address;
            // addr = &VRAM[apps.opt.Tiles_Base];
           
            int n = 0;
            for (int y = 0; y != app->tiles_height; y ++)
			{
                for (int x = 0; x != app->tiles_width; x ++)
                {
                    if ((addr - VRAM) > 0x4000)
                        break;
                    VDP_Mode0123_DrawTile(bmp, locked_region, tiles_frame_pos.x+(x * 8), tiles_frame_pos.y+(y * 8), addr, fg_color, bg_color);
                    if (n == tile_current)
					{
                        tile_current_addr = vram_addr_min + (n * 8);
						VDP_Mode0123_DrawTile(bmp, locked_region, tile_selected_pos.x, tile_selected_pos.y, addr, fg_color, bg_color);
					}

                    n++;
                    addr += 8;
                }
			}
            dirty = TRUE; // to be replaced later
            break;
        }
    }
	al_unlock_bitmap(app->box->gfx_buffer);

	// Refresh top status line (address range)
	al_set_target_bitmap(bmp);
	{
		// FIXME-OPT
		const int y = -1;
		al_draw_filled_rectangle(0, y + 1, app->vram_addr_tms9918_scrollbar->enabled ? app->vram_addr_tms9918_scrollbar->frame.pos.x-1 : 128-1, y + 11+1, COLOR_SKIN_WINDOW_BACKGROUND);

		char buf[64];
		sprintf(buf, "Range: $%04X-$%04X", vram_addr_min, vram_addr_min+vram_addr_size-1);
		Font_Print(FONTID_SMALL, buf, 0, y + 1, COLOR_SKIN_WINDOW_TEXT);
		dirty = true;
	}

    // Refresh bottom status line (selected tile)
    if (dirty_all || tile_current_refresh)
    {
		const int y = app->tiles_display_frame.GetMax().y;

        al_draw_filled_rectangle(16, y + 1, 127+1, y + 11+1, COLOR_SKIN_WINDOW_BACKGROUND);
        dirty = TRUE;

        if (tile_current != -1)
        {
            // Description
            char addr[16];
            if (tile_current_addr != -1)
                sprintf(addr, "$%04X", tile_current_addr);
            else
                sprintf(addr, "????");

			char buf[128];
			const int tile_index = tile_current_addr / vram_tile_size;
            sprintf(buf, Msg_Get(MSG_TilesViewer_Tile), tile_index, tile_index, addr);
            Font_Print(FONTID_SMALL, buf, 16, y + 1, COLOR_SKIN_WINDOW_TEXT);
            app->tile_displayed = tile_current;
        }
        else
        {
            // Fill tile with black
			const t_frame* fr = &app->tile_selected_frame;
            al_draw_filled_rectangle(fr->pos.x+2, fr->pos.y+2, fr->pos.x+2+8, fr->pos.y+2+8, COLOR_BLACK);
        }
    }

    if (dirty_all || dirty)
        app->dirty = FALSE;
}