I spent a couple hours to figure it out but no luck, so basically I've this configuration
$susy: (
columns: 12,
gutters: 54px/53px,
container: 1230px
);
In my layout file _layout.scss, I've this
#include layout( $susy inside );
.content-area {
padding-top: gutter( 6 );
.layout-2c-l & {
#include span( 8 of 12 no-gutters );
#include gutters(5); // 62.0625px
}
.archive.layout-2c-l &,
.search.layout-2c-l & {
padding-left: 0;
padding-right: 0;
}
}
In my case, on archive and search page I've to remove the gutters then re-added it via it's child elements like so in _archives.scss file
.page-header {
#include gutters(5); // 41.375px
}
As you can see the code above beside the gutters I add the pixel value, the first gutters resulting 62.0625px and the the second one 41.375px.
If this is how susy works, is there any way to get the same result?
Unless you set math: static in your Susy config, Susy will output % values based on the context that you give it. If you tell it that you are in a context of 5 both places, you will get the same % output — but that will translate into different px values if the parent containers are not actually the same width. So gutter(5) should only be used in places where the parent element spans 5 columns.
It's hard to tell from your sparse code sample, but it looks like you are maybe using the gutter context argument differently from how it is intended. When used correctly, you will always get a gutter ~54px (since that's what your settings specify).
Related
So, I had some old charts code using a very old Chart.js version 2.x but now due to the need of some functions only found on versions 3.x I'm updating a lot of code from the old charts on the website because a lot of the syntax changed between versions.
I just finished updating all charts and they are working nicely using plugins and etc, except for one.
On this type: 'bar' chart I have some very long strings on the 'X' axis, so I need to trim them to a max of 12 characters, but the tooltips need to show the whole string. The old code used to be this one and worked like a charm, right before rendering the chart I would set the updateScaleDefaults:
// Limit the size of label for 12 characters, tooltip on hover not changed
Chart.scaleService.updateScaleDefaults('category', {
ticks: {
callback: function(tick) {
var characterLimit = 12;
if ( tick.length >= characterLimit) {
return tick.slice(0, tick.length).substring(0, characterLimit -1).trim() + '...';;
}
return tick;
}
}
});
So right after that I would call the new Chart instance and would render it on a canvas. But now this code doesn't work anymore on v3.x, and I can't make an alternative version of this work.
As the migration guide for V3.x states on the documentation ,
Chart.scaleService was replaced with Chart.registry. Scale defaults are now in Chart.defaults.scales[type]
So I tried changing the first line of the code above to this and many other variations, trying to reuse the old code just changing the call to the object:
Chart.defaults.scales['category']
Nothing I tried worked.
I then tried creating a plugin with an beforeDraw, acessing the chart.scales.x.ticks and trying to make an arrow function on a map call, but I got a $context is a object error like this:
const pluginLimitTitle = {
beforeDraw: (chart) => {
console.log(chart.scales.x.ticks);
chart.scales.x.ticks = chart.scales.x.ticks.map(function (tick) {
var characterLimit = 12;
if (tick['label'].length >= characterLimit) {
return tick['label'].slice(0, tick['label'].length).substring(0, characterLimit - 1).trim() + '...';
;
}
return tick;
});
}
I also tried putting the ticks callback inside the options on the chart creation on options: scales: x: ticks but it did not work either way.
Can someone help me make this on v3.x?
Spent the whole day trying many things and don't look I'm getting closer to make it work.
After wasting many hours I found a "Tip" highlight on the documentation that should be in the examples, and not just badly highlighted on the "Labeling Axes" page.
When you do a callback for ticks on the chart options settings, you get 3 params to call:
function(value, index, ticks)
I tried in many ways to change the last one because it is the array of all ticks with their labels, and it is the only one where the label string appears so I was trying to modify it.
You'd think at first that the "value" parameter is the one to be changed, but it returns the exactly same integer value as the "index" parameter on each callback iteration, so I thought the only one the I could manipulate to change the string was the "ticks" array, but I was completely wrong.
You actually need to call a special function called getLabelForValue().
The working code ended up like this:
const configTotal = {
type: 'bar',
data: dataTotal,
options: {
scales: {
y: {
beginAtZero: true
},
x: {
ticks: {
callback: function(value, index, ticks_array) {
let characterLimit = 12;
let label = this.getLabelForValue(value);
if ( label.length >= characterLimit) {
return label.slice(0, label.length).substring(0, characterLimit -1).trim() + '...';
}
return label;
}
}
}
}
},
};
I hope this helps anyone having the same problem as me.
Maybe all the time I wasted is all on me for not reading every single line with more patience, but in my opinion, this documentation lacks a lot more example codes for accessing properties and callback parameters and it's object values, the way it is just showing the type of object and returns of each class method call, makes it very confusing for non-experienced on chart.js users.
I'm creating a visualization of sorting algorithms.
I've got a vector of QGraphicsRectItems which are columns with different height and the same width, generated on the app start. They are being shuffled and then added to a QGraphicsScene.
Class named "algorithms" sort a vector of float values which are used to set a height of columns. On swap - it emits a signal to the main class with two integers, so it looks like this:
emit comparison(array[first element to swap], array[second element to swap]);
Function(on_comparison) in the main class is connected with that signal. The problem appeared when I was trying to swap these 2 elements. I've created a variable to set n column position to it. After that I was trying to setPos of columns so I did something like:
void on_comparision(int n, int k)
{
auto nColumnPos = columns[n]->pos().x();
columns[n]->setX(columns[k]->pos().x());
columns[k]->setX(nColumnPos);
}
But it doesn't work. Positions are not changing.
Furthermore
qDebug() <<nColumnPos;
shows value = 0.
I was wondering if my whole program works so I decided to implement 2 sorting algorithms which swap 2 near each other elements and modified on_comparison function to
columns[n]->setX(columns[n].pos().x() + columnsWidth);
columns[n]->setX(columns[n].pos().x() - columnsWidth);
It works but doesn't give a satisfying result. This function will work only with sorting algorithms that swap 2 near each other elements except eg. Bubblesort/cocktailsort.
I was searching for the answer but didn't find anything helpful.
Here's the code:
https://gist.github.com/anonymous/e612e35a7c14eeb650099d4b997f437d
I've managed to solve the problem. The on_comparision function should look like this:
auto nRect = columns[n]->rect();
auto kRect = columns[k]->rect();
auto nColumnPos = nRect.left();
auto kColumnPos = kRect.left();
nRect.moveLeft(kColumnPos);
kRect.moveLeft(nColumnPos);
columns[n]->setRect(nRect);
columns[k]->setRect(kRect);
std::swap(columns[n], columns[k]);
instead of
auto nColumnPos = columns[n]->pos().x();
columns[n]->setX(columns[k]->pos().x());
columns[k]->setX(nColumnPos);
std::swap(columns[n], columns[k]);
QCircularBuffer has exactly what I need, but adding Qt3D to our compiler bloats the build too much and I'm the only one who needs it so I'm looking for some help figuring out how to write this kind of functionality.
QRingbuffer also is an additional include that I cannot use. This needs to be accomplished without adding any new libraries.
I'm using c++ and I've seen a couple of ideas but they always include using QLists without limiting its size.
I need the QList to be limited to say 10 items, and once the tenth item has been added, the old items are overwritten and new items are pushed to the front.
So for example, if the array contains [0,1,2,3,4,5,6,7,8,9], and we continue adding elements, we'll see this:
[10,1,2,3,4,5,6,7,8,9]
[11,10,2,3,4,5,6,7,8,9]
[12,11,10,3,4,5,6,7,8,9]
[13,12,11,10,4,5,6,7,8,9]
etc
Here is what I'm doing currently:
if(list.size() > 10)
list.push_front(newItem);
else
list.push_back(newItem);
Obviously this isn't limiting the size of the list, and it's not overwriting the oldest items, only the first.
Any help would be wonderful.
If you want them to push from the front with a max of ten then I would do something like this:
//somewhere higher up (maybe static) int curIndex = 0;
static const int LIST_SIZE = 10;
if(list.size() >= LIST_SIZE) //added an = here to make it 10 elements
{
list.removeAt(curIndex);
list.push_front(newItem);
curIndex = (curIndex + 1) % LIST_SIZE;
}
else
list.push_back(newItem);
Note: I do not have a compiler off hand to test this.
I am trying to do a little game, and in my game I have some squares and when the user click on these squares, they got highlighted. To achieve this effect I am using glutMouseFunc with glutTimerFunc.
When the user clicks on the screen I pick the pixel and identify the square I need to highlight. Once the square is identified I call glutTimerFunc. The function registred with glutTimerFunc increase the value of each component of color by 0.01 until they reach one max value defined by me, then this value goes back to a minimum value.
glutTimerFunc execute in 60 milliseconds and I get a almost smooth shine effect.
My problem is, if I click on two squares very fast, the effect starts on the first square, but don't finish, so the square remains highlighted and the second squares do the entire effect. If I click like a crazy man on every square, all of them got highlighted.
How can I make this effect of shining terminate even if I click on other square?
Here is a snippet of code
void Memoria::shineEffect(GLint value) {
if(value == 1) {
for(GLint i = 0; i < 3; i++) {
if(colors[selectedSquare][i] > 0) {
colors[selectedSquare][i] += COLOR_INCREASE;
if(colors[selectedSquare][i] >= MAX) {
colors[selectedSquare][i] = MAX;
value = -1;
}
}
}
glutTimerFunc(FPS, timeWrapper, value);
}
else {
if(value == -1) {
for(GLint i = 0; i < 3; i++) {
if(colors[selectedSquare][i] > 0) {
colors[selectedSquare][i] -= COLOR_INCREASE;
if(colors[selectedSquare][i] <= MIN) {
value = 0;
colors[selectedSquare][i] = MIN;
}
}
}
glutTimerFunc(FPS, timeWrapper, value);
}
}
}
timeWrapper calls shineEffect if the value passed in the parameter is 1 or -1.
You want the shineEffect function to go through one highlight loop at least, and then stop if the highlighted item has changed. It's more a UI code design issue rather than an OpenGL or GLUT one.
The mechanic you need to implement is pretty straightforward:
install once for all an updateHighlights function with glutTimerFunc: this function will be responsible of updating the highlights of all the clicked elements,
create a queue of elements: each time an element has been clicked, add it to the queue,
The task performed by the updateHighLights function should be as follow:
if the queue contains one element, keep cycling its highlight as you already do in your program
if the queue contain more than one element, for each element in the queue,
step the highlight cycle
if the cycle is over, and the element is not the last one, remove the element from the queue
Here's another perhaps more flexible take on your problem.
The Glut event loop machinery is very simple design: there's only one hook to put your "idle work" code, so it's probably more flexible to install a function there which calls a list of others functions. That list could be then modified with a set primitive, to install or remove specific tasks to perform during idle time. This could be much more flexible than the "one function" approach of GLUT.
For instance, you could isolate your current highlight code in one function with a struct containing the element to highlight, and have the function remove itself from the list when its element is done through a highlight cycle and isn't active anymore.
Since you are using C++, it should be easy to bundle all these functionalities in classes:
one class for the list of idle tasks
one base class for idle tasks
one derived idle task class for the purpose of highlighting a square (with fields for the square and for the active status)
one class to keep track of the active square, so that it may be easily deactivated and replaced by the new active one. This one would be accessed by the glutMouseFunc function.
This should be pretty easy but I'm having a heck of a time doing it. Basically I want to move a row in my wxListCtrl up or down. I posted this to wxwidgets forum and got the following code.
m_list->Freeze();
wxListItem item;
item.SetId(item_id); // the one which is selected
m_list->GetItem(item); // Retrieve the item
m_list->DeleteItem(item_id); // Remove it
item.SetId(item_id - 1); // Move it up
m_list->SetItem(item); // Apply it's new pos in the list
m_list->Thaw();
which doesn't work. The element is deleted but not moved up (I guess the setitem line is not working). Then I thought to just switch the text and the image but I can't even get the text from the row reliably. I have
int index = m_right->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
wxString label = m_right->GetItemText(index);
if(index == 0)
return;
wxListItem item;
item.SetId(index);
bool success = m_right->GetItem(item);
wxString text = item.GetText();
but text is blank even though there is text and the index is correct. So, I'm stuck not even being able to do the most basic task. Anybody know how to do this? The code runs in a button callback (the user presses a little up arrow and my code executes to try to move it). I'm using 2.9.1 on windows.
I made it work like this with wxWidgets 2.9.3 :
void FileSelectionPanel::OnMoveUp( wxCommandEvent& WXUNUSED(evt) )
{
int idx = _listCtrl->GetNextItem( -1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED );
if( idx == 0) idx = _listCtrl->GetNextItem( 0, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED );
_listCtrl->Freeze();
while( idx > -1 ) {
wxListItem item;
item.SetId(idx); _listCtrl->GetItem(item);
item.SetId(idx-1); _listCtrl->InsertItem(item);
_listCtrl->SetItemData( idx-1, _listCtrl->GetItemData( idx+1 ));
for( int i = 0; i < _listCtrl->GetColumnCount(); i++ ) {
_listCtrl->SetItem( idx-1, i, _listCtrl->GetItemText( idx+1, i ));
}
_listCtrl->DeleteItem( idx + 1 );
idx = _listCtrl->GetNextItem( idx-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED );
}
_listCtrl->Thaw();
}
The thing I noticed it that wxListItem is more of a convenience struct, for storing state of the view and help pass values into the wxListCtrl "nicely". It is in no way bound to what is actually inside of the wxListCtrl.
Hope this still helps anyone !
Even there is already an answer that is checked. I have the same problem here, but my list is unordered. By looking into wxWidgets' code I found out there is another important information inside the wxListItem object - the mask. I got my reordering to work correctly by setting the mask value to -1, which means that all data shall be copied. This includes the item text as well as other information, like the item data (which was important in my case).
wxListItem item;
item.SetId(item_id); // set needed id
item.SetMask(-1); // set needed data
m_list->GetItem(item); // actually retrieve the item
m_list->DeleteItem(item_id); // remove old copy
item.SetId(item_id - 1); // move item up
m_list->InsertItem(item); // insert copy of item
I also had to use "InsertItem" instead of "SetItem". Otherwise, there was no new item inserted, but an existing one overwritten (see also tomcat31's answer).
Is the list ordered? if it is auto ordering it may be ignoring the order you are trying to apply.
From recollection the internal order was not necessarily sequential, you might have to get the index of the previous item and go one before it.