About Store Forum Documentation Contact



Post Reply 
Berkelium Gui element
Author Message
yvanvds Offline
Member

Post: #1
Berkelium Gui element
Hi!

Here's the code for a berkelium gui element. It can be used to add browser windows to your app. Most of the code is borrowed from rndbit and andargor. they had a discussion about this in the offtopic section. I've combined the parts of the code there and added a bit of my own. So here's webwindow struct you can use as a more or less complete solution. It supports multiple browser windows, mouse and keyboard input. I've also added a small tutorial file.

What is not done?
* not all input keys are handled. (The arrow keys are not, for example)
* function handlers for back and forward navigation should be added
* it's not possible to resize the element. It shouldn't be hard to implement, but I don't need it for now.

Anyway, here's the code:

PHP Code:
/* stdafx.h: be sure to include berkelium before esenthel
   Also adjust library and include paths for berkelium, and put the 
   needed dll and berkelium exe in your exe directory
*/
/******************************************************************************/
#include <berkelium/Berkelium.hpp>
#include <berkelium/Context.hpp>
#include <berkelium/Window.hpp>
#include <berkelium/WindowDelegate.hpp>
#include <EsenthelEngine/EsenthelEngine.h>
/******************************************************************************/

/* main.cpp: the main program, use this like an EE tutorial
   A browser element gets focused if you click on it.
*/
/******************************************************************************/
#include "stdafx.h"
#include "webwindow.h"

// we'll create 2 browsers in this tutorial
webWindow Web1;
webWindow Web2;

void InitPre() {
  
App.name("Berkelium");
  
Paks.add("data/engine.pak");
  
D.sync(true);
}

Bool Init() {
  
Web1.create(Rect(-D.w(),0,D.w(),D.h()), "http://www.google.com");
  
Web2.create(Rect(-D.w(),-D.h(),D.w(),0), "http://attr-x.net");
  
Gui += Web1;
  
Gui += Web2;

  return 
true;
}

void Shut() {}

Bool Update() {
  if(
Kb.bp(KB_ESC  ))return false;

  
Gui.update();
  return 
true;
}

void Draw() {
  
D.clear(BLACK); 
  
Gui.draw();
}
/******************************************************************************/

/* webwindow.h: contains a struct extending a GuiImage with a browser 
   contains a nested class for berkelium callbacks
*/
/******************************************************************************/


struct webWindow : GuiImage {
  
Image            imgcube;
  
Berkelium::Window*  window;
  
Berkelium::Context*  context;
  
VecI2            size;
  
Int               wheel;

  
webWindow();
 ~
webWindow();

  
void         create(Rect& r, Str8 url);
  
virtual void update(GuiPC &gpc);
  
virtual void draw  (GuiPC &pgc);
  
void         handleEvents();

  
// declaration of draw function where onpaint goes
  
void DrawBerkelium(Berkelium::Window            *win                    ,
                     const 
unsigned char        *sourceBuffer            ,
                     const 
Berkelium::Rect      &sourceBufferRect        ,
                     
size_t                         numCopyRects            ,
                     const 
Berkelium::Rect      *copyRects                ,
                     
int                         dx                     , 
                     
int                         dy                     ,
                     const 
Berkelium::Rect      &scrollRect                );
    
  
friend class MyDelegate;

  
// Berkelium callback class
  
class MyDelegate : public Berkelium::WindowDelegate {
    
webWindow * self;
  public:
    
MyDelegate(webWindow * window) : self(window) {}

    
virtual void onStartLoading(Berkelium::Window *win, Berkelium::URLString newURL) {
      
Int i=0;
    }

    
virtual void onPaint(Berkelium::Window     *win             ,
                         const 
unsigned char   *sourceBuffer    ,
                         const 
Berkelium::Rect &sourceBufferRect,
                         
size_t                 numCopyRects    ,
                         const 
Berkelium::Rect *copyRects       ,
                         
int                    dx              , 
                         
int                    dy              ,
                         const 
Berkelium::Rect &scrollRect) {
      
self->DrawBerkelium(win,sourceBuffer,sourceBufferRect,numCopyRects,copyRects,dx,dy,scrollRect);
    }
  };
};

/******************************************************************************/

/* webwindow.cpp: the rest of the berkelium code and handler for key and
   mouse events
*/
/******************************************************************************/

#include "stdafx.h"
#include "webwindow.h"

UInt __berkeliumWindows = 0;

UInt berkTxtBtns[][3] = {
  { 
KB_ENTER  , 13        , 0 },
  { 
KB_ESC    , 27        , 0 },
  { 
KB_DEL    , 0x2E      , 0 },
  { 
KB_NPENTER, 13        , 0 },
  { 
KB_BACK   , (UInt)'\b', 0 }
};

UInt berkSpecBtns[][3] = {
  { 
KB_TAB, (UInt)'\t', 0 }
};

// DrawBerkelium, code ripped from rndbit :D
void webWindow::DrawBerkelium(    Berkelium::Window     *win,    
                                const 
unsigned char      *sourceBuffer, 
                                const 
Berkelium::Rect &sourceBufferRect,
                                
size_t                 numCopyRects       ,
                                const 
Berkelium::Rect *copyRects       ,
                                
int                    dx              , 
                                
int                       dy              ,
                                const 
Berkelium::Rect &scrollRect        ) {

  if(!
imgcube.is()) {
    
imgcube.create2D(size.x,size.y,IMAGE_B8G8R8A8);
  }

  
imgcube.lock();

  
unsigned char* texd = imgcube.data();
  
UInt tp = imgcube.pitch();
  
UInt tw = imgcube.x    ();
  
UInt th = imgcube.y    ();
  
UInt sz = tw*th*4;
    
  
// scrolling
  
{
    
Int wid  = scrollRect.width ();
    
Int hig  = scrollRect.height();
    
Int top  = scrollRect.top   ();
    
Int left = scrollRect.left  ();

    if(
dy < 0) {   // scroll down
      
for (int y = -dy; y < hig; y++) {
        
UInt tb = ((top + y) * tw + left) * 4;
        
UInt tb2 = tb + dy * tw * 4;
        if (
tb >= 0 && tb < sz && tb2 >= 0 && tb2 < sz) 
                
memcpy(&texd[tb2], &texd[tb], wid * 4);
      }
    }
    else if(
dy > 0) {   // scroll up
      
for (int y = hig - dy; y > -1; y--) {
        
UInt tb = ((top + y) * tw + left) * 4;
        
UInt tb2 = tb + dy * tw * 4;
        if (
tb >= 0 && tb < sz && tb2 >= 0 && tb2 < sz) 
                
memcpy(&texd[tb2], &texd[tb], wid * 4);
      }
    }

    if(
dx != 0) {    // scroll
      
int subx = dx > 0 ? 0 : -dx;
      for (
int y = 0; y < hig; y++) {
        
UInt tb = ((top + y) * tw + left) * 4;
        
UInt tb2 = tb - dx * 4;
        if (
tb >= 0 && tb < sz && tb2 >= 0 && tb2 < sz) 
                
memcpy(&texd[tb], &texd[tb2], wid * 4 - subx);
      }
    }
  }

  
// copy new rects
  
for(UInt i = 0; i < numCopyRects; i++) {
    
Berkelium::Rect cr = copyRects[i];
    
Int wid = cr.width();
    
Int hig = cr.height();
    
Int top = cr.top() - sourceBufferRect.top();
    
Int left = cr.left() - sourceBufferRect.left();

    for(
int y = 0; y < hig; y++) {
      
UInt tb = ((cr.top() + y) * tp + cr.left()* 4) ;
            
UInt tb2 = (left + (y + top) * sourceBufferRect.width()) * 4;
      
memcpy(&texd[tb], &sourceBuffer[tb2], wid * 4);
    }
  }

  
imgcube.unlock();
}

webWindow::webWindow() {
    
window = NULL;
    
context = NULL;
}

webWindow::~webWindow() {
  
window->destroy();
  
context->destroy();
  
__berkeliumWindows--;
  if (
__berkeliumWindows == 0) {
    
Berkelium::destroy();
  }
}

void webWindow::create(Rect& r, Str8 url) {
  
size = D.screenToPixel(r.rd()) - D.screenToPixel(r.lu());
    
  
// only initialize on first window
  
if (__berkeliumWindows == 0) {
    
Berkelium::init(Berkelium::FileString::empty());
  }
  
__berkeliumWindows++;

  
context = Berkelium::Context::create();
  
window  = Berkelium::Window::create(context);
  
window->resize     (size.x, size.y        );
  
window->setDelegate( new MyDelegate(this) ); // set callback class
  
window->focus      (                      ); 
  
window->navigateTo (url(), url.length()   );
  
super::create(r, &imgcube);
}

void webWindow::update(GuiPC &gpc) {
  
Berkelium::update();
  
handleEvents();
  
super::update(gpc);
}

void webWindow::draw(GuiPC &gpc) {
  
super::draw(gpc);
}

void webWindow::handleEvents() {
  if (
Cuts(Ms.pos(), T.rect)) {
    
// send mouse position
    
VecI2 pos = D.screenToPixel(Ms.pos()) - D.screenToPixel(T.pos());
    
window->mouseMoved(pos.x, pos.y);

    
// send mouse clicks and activate object if clicked
    
if(Ms.b(0)) {
      
window->mouseButton(0, true);
      
T.activate();
    }
    if(
Ms.b(1)) {
      
window->mouseButton(1, true);
      
T.activate();
    }
    if(
Ms.br(0)) window->mouseButton(0, false);
    if(
Ms.br(1)) window->mouseButton(1, false);

    
// send mouse wheel
    
if (Ms.wheel()!= 0) {
      
wheel = Ms.wheel() * 20;
      
window->mouseWheel(0, wheel);
    } else {
      
//smooth mouse wheel
      
if (wheel > 0) wheel--;
      else if (
wheel < 0) wheel++;
      
window->mouseWheel(0, wheel);
    }
  }

  
// send keys if this object has keyboard focus
  
int mods = 0;
  static 
UInt kbRepeatTimeout = 300;
  if (
Gui.ms() == this) {
    while (const 
Char8 c = Kb.c()) {
      if (
c == ' ' || c == 127 || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z') {
        
window->keyEvent(true, mods, c, 0);
      }
      
Char outchars[2] = { c, 0};
      
window->textEvent(outchars, 1);
      
Kb.nextBufferedChar();
    }
        
    for (
U32 i = 0; i < Elms(berkTxtBtns); i++) {
      
Bool bp = Kb.bp((KB_BUTTON)berkTxtBtns[i][0]);
      
UInt timeDiff = Time.curTimeMs() - berkTxtBtns[i][2];
      if (
bp || (Kb.b((KB_BUTTON)berkTxtBtns[i][0]) && timeDiff > kbRepeatTimeout)) {
        if (!
bp || timeDiff < 100) kbRepeatTimeout = 30;
        else 
kbRepeatTimeout = 300;
        
window->keyEvent(true, mods, berkTxtBtns[i][1], 0);
        
Char outchars[2] = {berkTxtBtns[i][1], 0 };
        
window->textEvent(outchars, 1);
        
berkTxtBtns[i][2] = Time.curTimeMs();
      }
    }

    for (
U32 i = 0; i < Elms(berkSpecBtns); i++) {
      
Bool bp = Kb.bp((KB_BUTTON)berkSpecBtns[i][0]);
      
UInt timeDiff = Time.curTimeMs() - berkSpecBtns[i][2];
      if (
bp || (Kb.b((KB_BUTTON)berkSpecBtns[i][0]) && timeDiff > kbRepeatTimeout)) {
        if (!
bp || timeDiff < 100) kbRepeatTimeout = 30;
        else 
kbRepeatTimeout = 300;
        
window->keyEvent(true, mods, berkSpecBtns[i][1], 0);
      }
    }

    
Kb.eat();    
  }
} 
09-14-2011 01:12 PM
Find all posts by this user Quote this message in a reply
rndbit Offline
Member

Post: #2
RE: Berkelium Gui element
good to see my buggy code was useful smile
10-10-2011 10:42 AM
Find all posts by this user Quote this message in a reply
Post Reply