1 /// module containing the button UI element 2 module ysge.ui.button; 3 4 import std.string; 5 import ysge.project; 6 7 alias ButtonOnClick = void delegate(Project, Button); 8 9 /// button UI element 10 class Button : UIElement { 11 private string label; /// the text that displays on the button 12 private SDL_Texture* labelTexture; 13 ButtonOnClick onClick; /// called when the button is clicked 14 SDL_Rect rect; /// the rectangle the button will be rendered in 15 SDL_Color fill; /// the background colour of the button 16 SDL_Color outline; /// the colour of the button outline 17 SDL_Color outlineHover; /// the colour of the button outline when the cursor is hovering on it 18 SDL_Color fillHover; /// the colour of the button fill when the cursor is hovering on it 19 SDL_Color labelColour; /// the colour of the label text 20 21 /// sets the button's label 22 void SetLabel(string newLabel) { 23 if (newLabel != label) { 24 labelTexture = null; 25 } 26 27 label = newLabel; 28 } 29 30 /// copies this UI element to a new class instance 31 Button CreateCopy() { 32 Button ret = new Button(); 33 34 ret.SetLabel(label); 35 ret.onClick = onClick; 36 ret.rect = rect; 37 ret.fill = fill; 38 ret.outline = outline; 39 ret.outlineHover = outlineHover; 40 ret.labelColour = labelColour; 41 42 return ret; 43 } 44 45 /// checks if a position is inside the button 46 bool OnButton(Vec2!int pos) { 47 return ( 48 (pos.x > rect.x) && 49 (pos.y > rect.y) && 50 (pos.x < rect.x + rect.w) && 51 (pos.y < rect.y + rect.h) 52 ); 53 } 54 55 override bool HandleEvent(Project project, SDL_Event e) { 56 switch (e.type) { 57 case SDL_MOUSEBUTTONDOWN: { 58 if (e.button.button != SDL_BUTTON_LEFT) { 59 return false; 60 } 61 62 auto mouse = project.mousePos; 63 64 if (OnButton(mouse)) { 65 onClick(project, this); 66 } 67 else { 68 return false; 69 } 70 break; 71 } 72 default: return false; 73 } 74 75 return false; 76 } 77 78 override void Render(Project project) { 79 auto fillColour = OnButton(project.mousePos)? fillHover : fill; 80 auto outlineColour = OnButton(project.mousePos)? outlineHover : outline; 81 82 SDL_SetRenderDrawColor( 83 project.renderer, fillColour.r, fillColour.g, fillColour.b, 84 fillColour.a 85 ); 86 SDL_RenderFillRect(project.renderer, &rect); 87 SDL_SetRenderDrawColor( 88 project.renderer, outlineColour.r, outlineColour.g, outlineColour.b, 89 outlineColour.a 90 ); 91 SDL_RenderDrawRect(project.renderer, &rect); 92 93 if (label.strip() == "") { 94 return; 95 } 96 97 if (labelTexture is null) { 98 SDL_Surface* labelSurface = TTF_RenderText_Solid( 99 project.font, toStringz(label), labelColour 100 ); 101 102 if (labelSurface is null) { 103 throw new ProjectException("Failed to render text"); 104 } 105 106 labelTexture = SDL_CreateTextureFromSurface( 107 project.renderer, labelSurface 108 ); 109 110 if (labelTexture is null) { 111 throw new ProjectException("Failed to create text texture"); 112 } 113 } 114 115 SDL_Rect textBox; 116 SDL_QueryTexture(labelTexture, null, null, &textBox.w, &textBox.h); 117 textBox.x = rect.x; 118 textBox.y = rect.y; 119 textBox.x += (rect.w / 2) - (textBox.w / 2); 120 textBox.y += (rect.h / 2) - (textBox.h / 2); 121 122 SDL_RenderCopy(project.renderer, labelTexture, null, &textBox); 123 } 124 }