UICollectionView cell starting margin - customization

I'm using a UICollectionView to display lottery numbers.
I want the cells of the collectionView to start after a custom spacing, and in that spacing i would like to display a Header, or a custom UIView of some kind.
now my collection view looks like this:
123
456
789
i would like it to look like this:
view12
345678
9.....
i'm thinking about using a custom layout, but the UICollectionViewFlowLayout serves my purpose.
is there any solution for this problem?

Solved.
since i only had to tweak the layout, just for a little bit, i decided to use a subclass of UICollectionViewFlowLayout.
this way, i can "play" with the layout as i wish, change the frame of headers/footers etc.
my solution works like this:
.h
#interface MyUICollectionViewFlowLayout : UICollectionViewFlowLayout
#end
.m
#define HEADER_VIEW_WIDTH 132
#define HEADER_VIEW_HEIGHT 44
#interface MyUICollectionViewFlowLayout ()
#end
#implementation MyUICollectionViewFlowLayout
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
NSMutableArray *allAttributes = [[super layoutAttributesForElementsInRect:rect] mutableCopy];
for (UICollectionViewLayoutAttributes *attribute in allAttributes) {
// if it's a cell, change it's layout to be right after the Header, and in the same line.
if (attribute.representedElementCategory == UICollectionElementCategoryCell) {
switch (attribute.indexPath.row) {
case 0:
attribute.frame = CGRectMake(HEADER_VIEW_WIDTH, 0, attribute.frame.size.width, attribute.frame.size.height);
break;
case 1:
attribute.frame = CGRectMake(HEADER_VIEW_WIDTH + attribute.frame.size.width , 0, attribute.frame.size.width, attribute.frame.size.height);
break;
case 2:
attribute.frame = CGRectMake(HEADER_VIEW_WIDTH + attribute.frame.size.width * 2 , 0, attribute.frame.size.width, attribute.frame.size.height);
break;
case 3:
attribute.frame = CGRectMake(HEADER_VIEW_WIDTH + attribute.frame.size.width * 3 , 0, attribute.frame.size.width, attribute.frame.size.height);
break;
case 4:
attribute.frame = CGRectMake(HEADER_VIEW_WIDTH + attribute.frame.size.width * 4 , 0, attribute.frame.size.width, attribute.frame.size.height);
break;
case 5:
attribute.frame = CGRectMake(HEADER_VIEW_WIDTH + attribute.frame.size.width * 5 , 0, attribute.frame.size.width, attribute.frame.size.height);
break;
case 6:
attribute.frame = CGRectMake(HEADER_VIEW_WIDTH + attribute.frame.size.width * 6 , 0, attribute.frame.size.width, attribute.frame.size.height);
break;
// if it's a header view, move it to the same line as all the cells.
} else if (attribute.representedElementCategory == UICollectionElementCategorySupplementaryView){
attribute.frame = CGRectMake(0, 0 , HEADER_VIEW_WIDTH, HEADER_VIEW_HEIGHT);
}
}
return allAttributes;
}
#end
i guess that instead of switch/case, i could have written some algorithm, but i prefer to leave optimization issues for later.

Related

How to fix std::shift_right not functioning properly with 2 element std::vector

I am currently working on a Snake game, everything functions as it should except the vector containing the snake body positions. The head of the snake should be the only initial element and after an apple has been eaten a new body part is added along with a trailing tail.
To move the snake body positions so it looks like they are part of the snake I use std::shift_right which works very well except for the first body part added. When the first part is added it is always inside the head/front of the vector. This makes it look like the snake has no growth/parts that follow.
As soon as the second apple is eaten the snake gets a 'tail'. The snake_body vector has now 3 elements while visually only having 2 on the game screen.
One apple has been eaten (snake_body is 2 long) but no tail
Two apples have been eaten (snake_body is 3 long) but has 1 part following instead of 2
How do I fix this?
(Thankyou in advance)
Related sample code:
std::vector <SDL_Point> snake_body = { SDL_Point(_PLAYER_START_POS) };
void Player::Movement()
{
switch (active_valid_input)
{
case SDLK_UP:
snake_body.front() = snake_body.front() + _MOVEMENT_UP;
break;
case SDLK_DOWN:
snake_body.front() = snake_body.front() + _MOVEMENT_DOWN;
break;
case SDLK_RIGHT:
snake_body.front() = snake_body.front() + _MOVEMENT_RIGHT;
break;
case SDLK_LEFT:
snake_body.front() = snake_body.front() + _MOVEMENT_LEFT;
break;
default:
break;
}
std::shift_right(snake_body.begin(), snake_body.end(), 1);
}
void Player::AddSnakePart() noexcept{
snake_body.push_back(snake_body.back());
}
You need to break up your movement, such that the shift happens between calculating the next head position, and assigning that position to head. At the moment your movement function leaves the head part in a moved-from state.
void Player::Movement()
{
SDL_Point next_head;
switch (active_valid_input)
{
case SDLK_UP:
next_head = snake_body.front() + _MOVEMENT_UP;
break;
case SDLK_DOWN:
next_head = snake_body.front() + _MOVEMENT_DOWN;
break;
case SDLK_RIGHT:
next_head = snake_body.front() + _MOVEMENT_RIGHT;
break;
case SDLK_LEFT:
next_head = snake_body.front() + _MOVEMENT_LEFT;
break;
default:
break;
}
std::shift_right(snake_body.begin(), snake_body.end(), 1);
snake_body.front() = next_head;
}
Aside: I would extract that switch into a function:
SDL_Point Player::Direction()
{
switch (active_valid_input)
{
case SDLK_UP: return _MOVEMENT_UP;
case SDLK_DOWN: return _MOVEMENT_DOWN;
case SDLK_RIGHT: return _MOVEMENT_RIGHT;
case SDLK_LEFT: return _MOVEMENT_LEFT;
}
}
void Player::Movement()
{
SDL_Point next_head = snake_body.front() + Direction();
std::shift_right(snake_body.begin(), snake_body.end(), 1);
snake_body.front() = next_head;
}
The issue was a simple matter of when I actually shifted the snake_body vector, I moved the std::shift_right before I applied the change to the front() position, it now functions properly.

How to auto wrap text with a dash in it?

In QStyledItemDelegate subclass paint method, the following code does not wrap the date-text as expected:
int flags = Qt::AlignCenter | Qt::TextWordWrap | Qt::TextJustificationForced;
switch (index.column())
{
case TimeRole:
{
int boxW = 16, space = 5, leftSpace = 30;
QRect textRect = QRect(rect.left() + leftSpace + boxW + space, rect.top(), rect.width() - boxW - space - m_space - leftSpace, rect.height());
QDateTime time = QDateTime::fromMSecsSinceEpoch(model->m_eventTime);
QString timeStr = time.toString("yyyy-MM-dd HH:mm:ss");
painter->drawText(textRect, flags, timeStr);
break;
}
However, I think because there is a dash -, text does not wrap as expected, instead, the left and the right characters are hidden:

Exception thrown by IJawsRenderer()

I’m using the Mako SDK and IJawsRenderer::render() to render all IDOMPathNodes with an IDOMImageBrush fill. When I do, the renderer throws an error 2000 exception for some nodes, but not all. What could be the cause?
IDOMBrushPtr pBrush;
pPath->getFill(pBrush);
if (pBrush)
{
IDOMBrush::eBrushType fillStyle = pBrush->getBrushType();
switch (fillStyle)
{
case IDOMBrush::eImage:
{
IJawsRendererPtr renderer = IJawsRenderer::create(jawsMako);
IDOMImagePtr renderedImage;
renderedImage = renderer->render(pNode, 800); // This is where the exception will eventually happen.
break;
}
default:
break;
}
}
It could be that the exception is thrown because the path passed to the renderer is too small. There is a lower limit of 1pt x 1pt (or 1.33 x 1.33 Mako units) for the renderer. Modify your code to check that the bounding box of the node is big enough, for example:
const double minimumRenderSize = 96.0 / 72.0;
...
IDOMBrushPtr pBrush;
pPath->getFill(pBrush);
FRect box;
pPath->getBounds(box);
box.dX = box.dX < minimumRenderSize ? minimumRenderSize : box.dX;
box.dY = box.dY < minimumRenderSize ? minimumRenderSize : box.dY;
if (pBrush)
{
IDOMBrush::eBrushType fillStyle = pBrush->getBrushType();
switch (fillStyle)
{
case IDOMBrush::eImage:
{
IJawsRendererPtr renderer = IJawsRenderer::create(jawsMako);
IDOMImagePtr renderedImage;
renderedImage = renderer->render(pNode, 800, IDOMColorSpacesRGB::create(jawsMako), box);
break;
}
default:
break;
}
}

Slow Paint() Performance

I want to display a customized item, basically a colored table with variable column number and width. I'm using c++ Builder XE2 Rad Studio for this.
So, I created a new class inherting from TGraphicControl overwriting void __fastcall Paint(void).
The Problem: it takes quite some time (between 15 and 30 ms) to draw 12 colored rectangles with text, so I expect to have done something wrong. I suspect ShadowRect to do things one could implement better, but I'm not really sure...
Does anyone see my mistake here?
Code to Draw the Paint() Event:
void __fastcall CustomTrgDrawings::Paint(void){
ResetCanvasTools();
ShadowRect(ClientRect,colBG-0x111111,coladdLight,colText,"");
Canvas->TextOutA(5,8,String().sprintf(L"Logic Box %u",fid));
Canvas->Font->Style = TFontStyles() << fsBold;
ShadowRect(nameRec,colBtnBG,coladdLight,colText,fName);
Canvas->Font->Style = TFontStyles() ;
ShadowRect(ch1Rec,colBtnBG-0x110011,coladdLight,colText,channels->Strings[fch1Id],true,3,true);
ShadowRect(ch2Rec,colBtnBG-0x110011,coladdLight,colText,channels->Strings[fch2Id],true,3,true);
ShadowRect(ch3Rec,colBtnBG-0x110011,coladdLight,colText,channels->Strings[fch3Id],true,3,true);
ShadowRect(ch4Rec,colBtnBG-0x110011,coladdLight,colText,channels->Strings[fch4Id],true,3,true);
ShadowRect(norm1Rec,colBtnBG-0x000011,coladdLight,colText,norms->Strings[fnorm1],true,3,true);
ShadowRect(norm2Rec,colBtnBG-0x000011,coladdLight,colText,norms->Strings[fnorm2],true,3,true);
ShadowRect(norm3Rec,colBtnBG-0x000011,coladdLight,colText,norms->Strings[fnorm3],true,3,true);
ShadowRect(norm4Rec,colBtnBG-0x000011,coladdLight,colText,norms->Strings[fnorm4],true,3,true);
ShadowRect(logicRec,colBtnBG-0x002222,coladdLight,colText,logics->Strings[flogicId],true,3,true);
ShadowRect(normOutRec,colBtnBG-0x002200,coladdLight,colText,norms->Strings[fnormOut],true,3,true);
}
void CustomTrgDrawings::ResetCanvasTools(){
Canvas->Brush->Color=clNone;
Canvas->Brush->Style=bsClear;
Canvas->Pen->Color=clNone;
Canvas->Pen->Mode=pmCopy;
Canvas->Pen->Style=psSolid;
Canvas->Pen->Width=1;
Canvas->Font->Color=clBlack;
Canvas->Font->Size=8;
Canvas->Font->Style=TFontStyles();
}
void CustomTrgDrawings::ShadowRect(const TRect pos,const TColor bg, const TColor add,const TColor fg, const String text,const bool shadow,const int align,const bool comboIcon){
int textLen;
int textX,textY;
int iconWidth=0;
Canvas->Brush->Style=bsSolid;
Canvas->Brush->Color=bg;
Canvas->Pen->Color=bg-4*add;
Canvas->Pen->Style=psSolid;
Canvas->Pen->Width=1;
Canvas->FillRect(pos);
if(shadow){
Canvas->Pen->Color=bg-2*add;
Canvas->MoveTo(pos.Left,pos.Bottom-1);
Canvas->LineTo(pos.Right-1,pos.Bottom-1);
Canvas->LineTo(pos.Right-1,pos.Top);
Canvas->Pen->Color=bg+2*add;
Canvas->MoveTo(pos.Right-1,pos.Top);
Canvas->LineTo(pos.Left,pos.Top);
Canvas->LineTo(pos.Left,pos.Bottom-1);
}
if(comboIcon){
iconWidth=6;
Canvas->Pen->Style=psSolid;
Canvas->Pen->Mode=pmMask;
Canvas->Pen->Width=3;
Canvas->Pen->Color=bg-2*add;
Canvas->MoveTo(pos.Right-iconWidth-5,pos.Top+6);
Canvas->LineTo(pos.Right-iconWidth/2-5,pos.Top+10);
Canvas->LineTo(pos.Right-5,pos.Top+6);
}
Canvas->Brush->Style=bsClear;
Canvas->Pen->Color=fg;
textLen=Canvas->TextWidth(text);
switch(align%3){ //horizontal position
case 0: //left
textX=3;
break;
case 1: //middle
textX=((pos.Width()-iconWidth)-textLen)/2;
break;
case 2: //right
textX=(pos.Width()-iconWidth)-textLen;
break;
}
switch(align/3){ //vertical position
case 0: //top
textY=-1;
break;
case 1: //middle
textY=(pos.Height()-Canvas->TextHeight(text))/2;
break;
case 2: //bottom
textY=pos.Height()-Canvas->TextHeight(text);
break;
}
Canvas->TextOutA(pos.Left+textX,pos.Top+textY,text);
}

How to move relatively to the angle?

I keep looking up on the internet how to move from point A to point B on an angle with a specified distance. When I tried to code it, however, the camera just gets messed up and I'm moving in random directions. I am using SDL/OpenGL with c++ and this is my player function. Right now, I'm trying to get the player to move forwards along the angle.
void player_action()
{
if (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_MOUSEMOTION:
{
player.rotxl = (screen->w)/2;
player.rotxd = event.motion.x - player.rotxl;
player.rotx = player.rotx + (player.rotxd/4);
if (player.rotx < 0)
{
player.rotx = player.rotx + 360;
};
if (player.rotx > 360)
{
player.rotx = player.rotx - 360;
}
};
break;
case SDL_KEYDOWN:
switch (event.key.keysym.sym)
{
case SDLK_w:
{player.zvel = 8.0f;}; break;
case SDLK_a:
{player.xvel = 8.0f;}; break;
case SDLK_s:
{player.zvel = -8.0f;}; break;
case SDLK_d:
{player.xvel = -8.0f;}; break;
case SDLK_ESCAPE:
{running = false;}; break;
default: break;
}; break;
case SDL_KEYUP:
switch(event.key.keysym.sym)
{
case SDLK_w:
{player.zvel = 0.0f;}; break;
case SDLK_a:
{player.xvel = 0.0f;}; break;
case SDLK_s:
{player.zvel = 0.0f;}; break;
case SDLK_d:
{player.xvel = 0.0f;}; break;
default: break;
};
break;
};
};
player.x = player.x + float(player.zvel*cos((double)player.rotx));
player.z = player.z + float(player.zvel*sin((double)player.rotx));
glRotatef(player.rotx, 0.0f, 1.0f, 0.0f);
glTranslatef(player.x, player.y, player.z);
SDL_WarpMouse((screen->w/2), (screen->h/2));
};
If I'm correct the math functions sin and cos both take angles in radians, not degrees as player.rotx seems to be. Try the following:
player.x = player.x + float(player.zvel*cos((double)player.rotx*0.0174532925));
player.z = player.z + float(player.zvel*sin((double)player.rotx*0.0174532925));
We're multiplying player.rotx by pi/180, which is how we convert degrees to radians.
Not sure if this is your only problem, but it certainly appears to be one of them.
Two possible sources of the issue I see:
The standard C++ cos/sin function take a function in radians instead of degrees (one radian = 180/pi degrees).
While I'm not familiar with SDL a quick look at the docs makes me think you should be using event.motion.xrel instead of .x. You'll have to change your rotx calculation which should not need the screen width.