/* ScummVM - Graphic Adventure Engine * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include "ultima/nuvie/core/nuvie_defs.h" #include "ultima/nuvie/gui/gui_button.h" #include "ultima/nuvie/gui/gui_load_image.h" namespace Ultima { namespace Nuvie { /* the check marks bitmap */ Graphics::ManagedSurface *checkmarks = nullptr; GUI_Button:: GUI_Button(void *data, int x, int y, Graphics::ManagedSurface *image, Graphics::ManagedSurface *image2, GUI_CallBack *callback, bool free_surfaces) : GUI_Widget(data, x, y, image->w, image->h), callback_object(callback), button(image), button2(image2), freebutton(free_surfaces), enabled(true), buttonFont(nullptr), freefont(false), flatbutton(false), is_checkable(false), checked(0), is_highlighted(false) { for (int i = 0; i < 3; ++i) { pressed[i] = 0; } } GUI_Button::GUI_Button(void *data, int x, int y, int w, int h, GUI_CallBack *callback) : GUI_Widget(data, x, y, w, h), callback_object(callback), button(nullptr), button2(nullptr), freebutton(false), enabled(true), buttonFont(nullptr), freefont(false), flatbutton(false), is_checkable(false), checked(0), is_highlighted(false) { for (int i = 0; i < 3; ++i) { pressed[i] = 0; } } GUI_Button::GUI_Button(void *data, int x, int y, int w, int h, const char *text, GUI_Font *font, ButtonTextAlign alignment, bool is_checkbutton, GUI_CallBack *callback, bool flat) : GUI_Widget(data, x, y, w, h) { callback_object = callback; if (font != nullptr) { buttonFont = font; freefont = false; } else { buttonFont = new GUI_Font(); freefont = true; } flatbutton = flat; freebutton = true; button = nullptr; button2 = nullptr; is_checkable = is_checkbutton; checked = 0; is_highlighted = false; /* if (is_checkable &&(checkmarks==nullptr)) { checkmarks=GUI_LoadImage(checker_w,checker_h,checker_pal,checker_data); SDL_SetColorKey(checkmarks,SDL_SRCCOLORKEY,0); } */ ChangeTextButton(-1, -1, -1, -1, text, alignment); for (int i = 0; i < 3; ++i) { pressed[i] = 0; } enabled = true; } GUI_Button::~GUI_Button() { if (freebutton) { if (button) delete button; if (button2) delete button2; } if (freefont) delete buttonFont; } /* Resize/reposition/change text */ void GUI_Button::ChangeTextButton(int x, int y, int w, int h, const char *text, ButtonTextAlign alignment) { if (x != -1 || y != -1) { assert(x >= 0 && y >= 0); area.moveTo(x, y); } if (w != -1 || h != -1) { assert(w >= 0 && h >= 0); area.setWidth(w); area.setHeight(h); } if (freebutton) { if (button) delete button; if (button2) delete button2; if (flatbutton) { button = CreateTextButtonImage(BUTTON2D_UP, text, alignment); button2 = CreateTextButtonImage(BUTTON2D_DOWN, text, alignment); } else { button = CreateTextButtonImage(BUTTON3D_UP, text, alignment); button2 = CreateTextButtonImage(BUTTON3D_DOWN, text, alignment); } } } /* Show the widget */ void GUI_Button:: Display(bool full_redraw) { Common::Rect src, dest = area; if (button) { if ((button2 != nullptr) && ((pressed[0]) == 1 || is_highlighted)) SDL_BlitSurface(button2, nullptr, surface, &dest); else SDL_BlitSurface(button, nullptr, surface, &dest); } if (is_checkable) { src.left = 8 - (checked * 8); src.top = 0; src.setWidth(8); src.setHeight(10); dest.left += 4; dest.top += 4; dest.setWidth(8); dest.setHeight(10); SDL_BlitSurface(checkmarks, &src, surface, &dest); } if (!enabled) { uint8 *pointer; int pixel = surface->format.RGBToColor(0, 0, 0); uint8 bytepp = surface->format.bytesPerPixel; for (int y = 0; y < area.height(); y += 2) { pointer = (uint8 *)surface->getPixels() + surface->pitch * (area.top + y) + (area.left * bytepp); for (int x = 0; x> 1; x++) { switch (bytepp) { case 1: *((uint8 *)(pointer)) = (uint8)pixel; pointer += 2; break; case 2: *((uint16 *)(pointer)) = (uint16)pixel; pointer += 4; break; case 3: /* Format/endian independent */ uint8 r, g, b; r = (pixel >> surface->format.rShift) & 0xFF; g = (pixel >> surface->format.gShift) & 0xFF; b = (pixel >> surface->format.bShift) & 0xFF; *((pointer) + surface->format.rShift / 8) = r; *((pointer) + surface->format.gShift / 8) = g; *((pointer) + surface->format.bShift / 8) = b; pointer += 6; break; case 4: *((uint32 *)(pointer)) = (uint32)pixel; pointer += 8; break; } } } } DisplayChildren(); } /* Mouse hits activate us */ GUI_status GUI_Button:: MouseDown(int x, int y, Events::MouseButton btn) { // if(btn == SDL_BUTTON_WHEELUP || btn == SDL_BUTTON_WHEELDOWN) // return GUI_PASS; if (enabled && (btn == Events::BUTTON_LEFT || btn == Events::BUTTON_RIGHT)) { pressed[0] = 1; Redraw(); } return GUI_YUM; } GUI_status GUI_Button::MouseUp(int x, int y, Events::MouseButton btn) { // if (btn==SDL_BUTTON_WHEELUP || btn==SDL_BUTTON_WHEELDOWN) // return GUI_PASS; if ((btn == Events::BUTTON_LEFT || btn == Events::BUTTON_RIGHT) && (pressed[0])) { pressed[0] = 0; return Activate_button(x, y, btn); } return GUI_YUM; } GUI_status GUI_Button::Activate_button(int x, int y, Events::MouseButton btn) { if (x >= 0 && y >= 0) { if (callback_object && callback_object->callback(BUTTON_CB, this, widget_data) == GUI_QUIT) return GUI_QUIT; } Redraw(); return GUI_YUM; } GUI_status GUI_Button::MouseMotion(int x, int y, uint8 state) { if ((pressed[0] == 1) && ((x < 0) || (y < 0))) { pressed[0] = 2; Redraw(); } if ((pressed[0] == 2) && (x >= 0) && (y >= 0)) { pressed[0] = 1; Redraw(); } return GUI_YUM; } void GUI_Button::Disable() { enabled = false; Redraw(); } void GUI_Button::Enable(bool flag) { enabled = flag; Redraw(); } Graphics::ManagedSurface *GUI_Button::CreateTextButtonImage(int style, const char *text, ButtonTextAlign alignment) { Common::Rect fillrect; int th, tw; int tx = 0, ty = 0; char *duptext = nullptr; Graphics::ManagedSurface *img = new Graphics::ManagedSurface(area.width(), area.height(), Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0)); if (img == nullptr) return nullptr; uint32 color1 = img->format.RGBToColor(BL_R, BL_G, BL_B); uint32 color2 = img->format.RGBToColor(BS_R, BS_G, BS_B); uint32 color3 = img->format.RGBToColor(BF_R, BF_G, BF_B); uint32 color4 = img->format.RGBToColor(BI2_R, BI2_G, BI2_B); buttonFont->setColoring(0, 0, 0); buttonFont->setTransparency(true); buttonFont->textExtent(text, &tw, &th); int checkable = (is_checkable ? 1 : 0); if (tw > (area.width() - (4 + checkable * 16))) { int n = (area.width() - (4 + checkable * 16)) / buttonFont->charWidth(); duptext = new char[n + 1]; strncpy(duptext, text, n); duptext[n] = 0; text = duptext; buttonFont->textExtent(text, &tw, &th); } if (th > (area.height() - 4)) { text = ""; } switch (alignment) { case BUTTON_TEXTALIGN_LEFT: tx = 4 + (checkable * 16); break; case BUTTON_TEXTALIGN_CENTER: tx = (area.width() - tw) >> 1; break; case BUTTON_TEXTALIGN_RIGHT: tx = area.width() - 5 - tw; break; } ty = (area.height() - th) >> 1; if (!area.isEmpty()) { switch (style) { case BUTTON3D_UP: fillrect = Common::Rect(area.width(), 2); SDL_FillRect(img, &fillrect, color1); fillrect.moveTo(0, area.height() - 2); SDL_FillRect(img, &fillrect, color2); fillrect = Common::Rect(2, area.height()); SDL_FillRect(img, &fillrect, color1); fillrect.moveTo(area.width() - 2, 0); SDL_FillRect(img, &fillrect, color2); fillrect.setHeight(1); fillrect.setWidth(1); SDL_FillRect(img, &fillrect, color1); fillrect.moveTo(1, area.height() - 1); SDL_FillRect(img, &fillrect, color2); fillrect = Common::Rect(2, 2, area.width() - 2, area.height() - 2); SDL_FillRect(img, &fillrect, color3); buttonFont->textOut(img, tx, ty, text); break; case BUTTON3D_DOWN: fillrect = Common::Rect(area.width(), area.height()); SDL_FillRect(img, &fillrect, color3); buttonFont->textOut(img, tx + 1, ty + 1, text); break; case BUTTON2D_UP: fillrect = Common::Rect(area.width(), area.height()); SDL_FillRect(img, &fillrect, color3); buttonFont->textOut(img, tx, ty, text); break; case BUTTON2D_DOWN: fillrect = Common::Rect(area.width(), area.height()); SDL_FillRect(img, &fillrect, color4); buttonFont->setTransparency(false); buttonFont->setColoring(BI1_R, BI1_G, BI1_B, BI2_R, BI2_G, BI2_B); buttonFont->textOut(img, tx, ty, text); break; } } delete[] duptext; return img; } } // End of namespace Nuvie } // End of namespace Ultima