A pagination system for dialogs in SA-MP & open.mp written in Pawn. It splits large amounts of text into dialog pages using different pagination modes.
Supported dialog styles: DIALOG_STYLE_MSGBOX, DIALOG_STYLE_LIST, DIALOG_STYLE_TABLIST, DIALOG_STYLE_TABLIST_HEADERS.
- Support mdialog (optional).
- Support zlang (optional).
- Static lines on the first page.
- Manual mode for modules.
Simply install the package into your project:
sampctl package install NikitaFoxze/flip-dialogInclude it in your code and start using the library:
#include <flip-dialog>Click to expand the list
DialogPagin_Open(playerid, const function[], style, max_lines_on_page, const caption[], {Float, _}:...)
Open a dialog with pagination
playerid- The ID of the player opening the dialogstyle- Dialogue stylemax_lines_on_page- Maximum number of lines per pagecaption[]- Dialogue title- Returns
1 (true)if the function was successful, or0 (false)if the dialog was not opened
DialogPagin_AddLine(playerid, color, const text[], {Float, _}:...)
Add a line
playerid- The ID of the player adding the linecolor- Numbering color[%i]text[]- Text of the line- Returns
1 (true)if the function succeeded, or0 (false)if the line was not added
DialogPagin_AddStaticLine(playerid, color, const text[], {Float, _}:...)
Add a static line
playerid- The ID of the player adding the static linecolor- Numbering color[%i]text[]- Text of the line- Returns
1 (true)if the function succeeded, or0 (false)if the static line was not added
DialogPagin_SetTablist(playerid, const text[], {Float, _}:...)
Add tab list (for
DIALOG_STYLE_TABLIST_HEADERS)
playerid- The ID of the player adding the list of tabstext[]- Tab list text- Returns nothing
DialogPagin_SetLineID(playerid, abstractid)
Set abstract line ID (used with
DialogPagin_AddLine)
playerid- The player ID that adds an abstract IDabstractid- Abstract ID for further use- Returns
1 (true)if the function succeeded, or0 (false)if no ID was specified
DialogPagin_GetSelectLineID(playerid)
Return the ID of the line selected by the player, specified when it was added (used in
OnDialogResponse)
playerid- The ID of the player receiving the abstract ID- Returns a previously added abstract ID
DialogPagin_SetLineName(playerid, const abstract_name[])
Set an abstract name for a line (used with
DialogPagin_AddLine)
playerid- The player ID that adds an abstract nameabstract_name[]- Abstract name for future use- Returns
1 (true)if the function succeeded, or0 (false)if no name was specified.
DialogPagin_GetSelectLineName(playerid, output[], const size = sizeof(output))
Return the name of the line selected by the player, specified when it was added (used in
OnDialogResponse)
playerid- The ID of the player receiving the abstract nameoutput[]- Returned string with abstract namesize- String size- Returns nothing
DialogPagin_ChangeCaption(playerid, const text[], {Float, _}:...)
Change the dialog title
playerid- The player's ID that changes the titletext[]- Headline text- Returns nothing
DialogPagin_IsOpen(playerid, const function[] = "")
Check if a dialog with pagination is open (if using
mdialog, theDialog_IsOpenfunction will work correctly)
playerid- The ID of the player checking the dialogfunction[]- Dialog function, optional argument- Returns
1 (true)if a pagination dialog is open, or0 (false)if not.
DialogPagin_GetTotalLines(playerid)
Return the number of all rows
playerid- The ID of the player receiving the number of lines- Returns the number of all rows
DialogPagin_GetMaxLinesOnPage(playerid)
Reset the maximum number of lines per page
playerid- The ID of the player receiving the number of lines- Returns the maximum number of rows per page.
DialogPagin_IsFirstPage(playerid)
Check for an open first page
playerid- The ID of the player receiving the page- Returns
1 (true)if the first page is open, or0 (false)if not.
DialogPagin_IsLastPage(playerid)
Check the last page that is open
playerid- The ID of the player receiving the page- Returns
1 (true)if the last page is open, or0 (false)if not.
DialogPagin_ReOpen(playerid)
Open the last closed dialog with pagination
playerid- The ID of the player opening the dialog- Returns
1 (true)if the function was successful, or0 (false)if the dialog was not opened.
DialogPagin_SetMode(playerid, modeid)
Set pagination mode (use before all functions)
playerid- The ID of the player opening the dialogmodeid- Pagination mode identifier (FDIALOG_MODE_AUTO,FDIALOG_MODE_MANUAL)- Returns nothing
DialogPagin_ProcessManual(playerid, total_lines = 0)
Handle and open a dialog with manual mode (use in
OnDialogResponse)
playerid- The ID of the player opening the dialogtotal_lines- The total number of lines. If you don't enter anything, the maximum number of lines on the page plus 1 will be taken into account. If you enter the total number of lines, for example, from an array, it will also work.- Returns
1 (true)if the function was successful, or0 (false)if the dialog was not opened.
DialogPagin_ResetData(playerid)
Reset all pagination data if necessary
playerid- The player ID that is resetting the data- Returns nothing
// If you want to change the text, just set these parameters
#define FDIALOG_TEXT_EMPTY "{FFFFFF}Empty..."
#define FDIALOG_TEXT_SELECT "O"
#define FDIALOG_TEXT_CLOSE "X"
#define FDIALOG_TEXT_NUMERATION "[%i]"
// For the DIALOG_STYLE_MSGBOX style
#define FDIALOG_MESSAGE_TEXT_NEXT "››"
#define FDIALOG_MESSAGE_TEXT_BACK "‹‹"
// For other styles
#define FDIALOG_LIST_TEXT_NEXT "{A0A0A0}>>>"
#define FDIALOG_LIST_TEXT_BACK "{A0A0A0}<<<"
#include <flip-dialog>
new nicknames[][MAX_PLAYER_NAME + 1] =
{
"Foxze", "Ziggi", "Nexius", "Neuty", "Kalcor",
"Kocmoc", "DELIVER", "Roberto_Coluccio", "Artem_Gorden",
"Danil_Marciface", "VanilaSW", "Dima_Rendi", "Fix_Unvardo", "Itsuki_Yorimoto",
"Flatt_Delx", "Fredorico_Viton", "Demetrio_Santini", "Maks_Anurov",
"Vladislav_Barsov", "Doni_Visage", "Richi_Klay", "Sebastian_Undeground"
};
CMD:fdtest(playerid) // Needs Pawn.CMD
{
for (new i; i < sizeof(nicknames); i++) {
DialogPagin_AddLine(playerid, 0xFF6347FF, // 0x00000000 - removes numbering
"{FFFFFF}Nickname - %s",
nicknames[i]);
}
DialogPagin_Open(playerid, Dialog:TestDialog, DIALOG_STYLE_LIST, 10,
"{FF6347}Basic usage");
return 1;
}
DialogResponse:TestDialog(playerid, response, listitem, inputtext[])
{
if (!response) {
// Your code...
return 1;
}
// Your code...
return 1;
}Support mdialog
#include <mdialog>
#include <flip-dialog>
DialogCreate:TestDialog(playerid)
{
for (new i; i < 100; i++) {
DialogPagin_AddLine(playerid, 0xFF6347FF,
"{FFFFFF}Number - %i", i);
}
DialogPagin_Open(playerid, Dialog:TestDialog, DIALOG_STYLE_LIST, 10,
"{FF6347}Basic usage");
return 1;
}
DialogResponse:TestDialog(playerid, response, listitem, inputtext[])
{
if (!response) {
// Your code...
return 1;
}
// Your code...
return 1;
}Static lines can only be added once per dialog. They appear only on the first page.
CMD:fdtest(playerid)
{
DialogPagin_AddStaticLine(playerid, 0xFFAC55FF,
"{FFFFFF}Tab 1");
DialogPagin_AddStaticLine(playerid, 0xFFAC55FF,
"{FFFFFF}Tab 2");
DialogPagin_AddStaticLine(playerid, 0xFFAC55FF,
"{FFFFFF}Tab 3");
for (new i; i < sizeof(nicknames); i++) {
DialogPagin_AddLine(playerid, 0xFF6347FF,
"{FFFFFF}%s", nicknames[i]);
}
DialogPagin_Open(playerid, Dialog:TestDialog, DIALOG_STYLE_LIST, 10,
"{FF6347}Static lines");
return 1;
}
DialogResponse:TestDialog(playerid, response, listitem, inputtext[])
{
if (!response) {
// Your code...
return 1;
}
// Static lines
if (DialogPagin_IsFirstPage(playerid)) {
switch (listitem) {
case 0: {
SendClientMessage(playerid, -1, "Tab 1");
return 1;
}
case 1: {
SendClientMessage(playerid, -1, "Tab 2");
return 1;
}
case 2: {
SendClientMessage(playerid, -1, "Tab 3");
return 1;
}
}
}
// Your code...
return 1;
}Each line can be assigned an abstract ID or name, which allows one to determine what data the line the player selected contained.
CMD:fdtest(playerid)
{
for (new i; i < sizeof(nicknames); i++) {
DialogPagin_AddLine(playerid, 0xFF6347FF,
"{FFFFFF}Nickname - %s", nicknames[i]);
// The line is given the desired name.
DialogPagin_SetLineName(playerid,
nicknames[i]);
}
DialogPagin_Open(playerid, Dialog:TestDialog, DIALOG_STYLE_LIST, 10,
"{FF6347}Data storage for lines");
return 1;
}
DialogResponse:TestDialog(playerid, response, listitem, inputtext[])
{
if (!response) {
// Your code...
return 1;
}
new
string[64],
playerName[MAX_PLAYER_NAME + 1];
// The name is taken from the line chosen by the player
DialogPagin_GetSelectLineName(playerid, playerName);
format(string, sizeof(string), "Select %s", playerName);
SendClientMessage(playerid, 0xFFFFFFFF, string);
return 1;
}Why use it? This mode is designed for working with huge amounts of text and situations where you need full control over the pagination process.
In manual mode, the pagination system displays only one page at a time and does not keep track of previous or next pages. You decide which page to display instead of passing the entire text array to the pagination system in advance.
This mode is also useful for loading data asynchronously in chunks: you can load a specific amount of data, display it, and then continue the pagination process after loading the next chunk.
In this mode, you need to declare your own variable to control the pagination Offset. The system does not know how many rows need to be processed in total: it only works with the current page and processes as many rows as you specify.
The system can only be provided with one of two states: whether there is a next page or there are no more pages.
The first option is to pass the array size to the DialogPagin_ProcessManual function, for example, sizeof(nicknames), or the total number of rows.
The second option is to add one more line using DialogPagin_AddLine than can fit on a single page. This allows the pagination system to determine whether there is a next page when the total number of rows is unknown.
Note: If you need to pause the current process in
DialogResponseor open another dialog usingShowPlayerDialog, it is recommended to useDialogPagin_ResetData.DialogPagin_ResetDatais not required whenresponseisFDIALOG_RESPONSE_CLOSEorFDIALOG_RESPONSE_SELECT, or when opening a dialog usingDialog_Showfrommdialog.
This example demonstrates the first option, while the second option is available in flip-dialog-mysql.inc.
// Declaring a variable for offset
new
test_offset[MAX_PLAYERS];
CMD:fdtest(playerid)
{
// Setting the mode
DialogPagin_SetMode(playerid, FDIALOG_MODE_MANUAL);
DialogPagin_Open(playerid, Dialog:TestDialog, DIALOG_STYLE_LIST, 6,
"{FF6347}Manual mode");
return 1;
}
DialogResponse:TestDialog(playerid, response, listitem, inputtext[])
{
// Declaring a variable for offset
new
start_offset,
next_offset,
max_lines_on_page = DialogPagin_GetMaxLinesOnPage(playerid);
switch (response) {
// Closing the dialog
case FDIALOG_RESPONSE_CLOSE: {
// Your code...
return 1;
}
// Selecting a line
case FDIALOG_RESPONSE_SELECT: {
// Your code...
return 1;
}
// First opening of the dialogue
case FDIALOG_RESPONSE_INIT: {
start_offset = 0;
next_offset = max_lines_on_page;
test_offset[playerid] = start_offset;
}
// Next page
case FDIALOG_RESPONSE_NEXT_PAGE: {
start_offset = test_offset[playerid] + max_lines_on_page;
next_offset = start_offset + max_lines_on_page;
test_offset[playerid] = start_offset;
}
// Previous page
case FDIALOG_RESPONSE_BACK_PAGE: {
start_offset = test_offset[playerid] - max_lines_on_page;
if (start_offset < 0) {
start_offset = 0;
}
next_offset = start_offset + max_lines_on_page;
test_offset[playerid] = start_offset;
}
}
new
total_lines = sizeof(nicknames);
// Adding lines
for (new i = start_offset; i < next_offset && i < total_lines; i++) {
DialogPagin_AddLine(playerid, 0xFF6347FF,
"{FFFFFF}%s",
nicknames[i]);
}
// Processing and displaying dialogue
DialogPagin_ProcessManual(playerid, total_lines);
return 1;
}A separate manual mode module for loading data using the LIMIT clause in MySQL queries. Designed for convenient paginated loading without unnecessary logic.
#include <flip-dialog>
#include <flip-dialog-mysql>
CMD:fdtest(playerid)
{
DPMySQL_Open(playerid, Dialog:TestDialog, DIALOG_STYLE_LIST,
10, db_handle,
"SELECT \
`nickname` \
FROM `player_accounts` \
ORDER BY `id` ASC",
"Nicknames from the database");
return 1;
}
DialogResponse:TestDialog(playerid, response, listitem, inputtext[])
{
switch (response) {
case FDIALOG_RESPONSE_CLOSE: {
// Your code...
return 1;
}
case FDIALOG_RESPONSE_SELECT: {
// Your code...
return 1;
}
case FDIALOG_RESPONSE_LOAD_DATA: {
new
playerName[MAX_PLAYER_NICKNAME + 1];
for (new i; i < cache_num_rows(); i++) {
cache_get_value(i, "nickname", playerName);
DialogPagin_AddLine(playerid,
0xFF6347FF,
"{FFFFFF}%s",
playerName);
}
}
}
DialogPagin_ProcessManual(playerid);
return 1;
}

