1319 /* No action ;) */ |
1311 /* No action ;) */ |
1320 } |
1312 } |
1321 |
1313 |
1322 |
1314 |
1323 |
1315 |
1324 /** |
1316 struct NetworkClientListPopupWindow : Window { |
1325 * An action is clicked! What do we do? |
1317 int sel_index; |
1326 */ |
1318 int client_no; |
1327 static void HandleClientListPopupClick(byte index, byte clientno) |
1319 char action[MAX_CLIENTLIST_ACTION][50]; |
1328 { |
1320 ClientList_Action_Proc *proc[MAX_CLIENTLIST_ACTION]; |
1329 /* A click on the Popup of the ClientList.. handle the command */ |
1321 |
1330 if (index < MAX_CLIENTLIST_ACTION && _clientlist_proc[index] != NULL) { |
1322 NetworkClientListPopupWindow(int x, int y, const Widget *widgets, int client_no) : |
1331 _clientlist_proc[index](clientno); |
1323 Window(x, y, 150, 100, NULL, WC_TOOLBAR_MENU, widgets), |
1332 } |
1324 sel_index(0), client_no(client_no) |
1333 } |
1325 { |
1334 |
1326 /* |
1335 /** |
1327 * Fill the actions this client has. |
1336 * Finds the amount of clients and set the height correct |
1328 * Watch is, max 50 chars long! |
1337 */ |
1329 */ |
1338 static bool CheckClientListHeight(Window *w) |
1330 |
1339 { |
1331 const NetworkClientInfo *ci = NetworkFindClientInfo(client_no); |
1340 int num = 0; |
1332 |
1341 const NetworkClientInfo *ci; |
1333 int i = 0; |
1342 |
1334 if (_network_own_client_index != ci->client_index) { |
1343 /* Should be replaced with a loop through all clients */ |
1335 GetString(this->action[i], STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT, lastof(this->action[i])); |
1344 FOR_ALL_ACTIVE_CLIENT_INFOS(ci) { |
1336 this->proc[i++] = &ClientList_SpeakToClient; |
1345 num++; |
1337 } |
1346 } |
1338 |
1347 |
1339 if (IsValidPlayer(ci->client_playas) || ci->client_playas == PLAYER_SPECTATOR) { |
1348 num *= CLNWND_ROWSIZE; |
1340 GetString(this->action[i], STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY, lastof(this->action[i])); |
1349 |
1341 this->proc[i++] = &ClientList_SpeakToCompany; |
1350 /* If height is changed */ |
1342 } |
1351 if (w->height != CLNWND_OFFSET + num + 1) { |
1343 GetString(this->action[i], STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL, lastof(this->action[i])); |
1352 // XXX - magic unfortunately; (num + 2) has to be one bigger than heigh (num + 1) |
1344 this->proc[i++] = &ClientList_SpeakToAll; |
1353 w->SetDirty(); |
1345 |
1354 w->widget[3].bottom = w->widget[3].top + num + 2; |
1346 if (_network_own_client_index != ci->client_index) { |
1355 w->height = CLNWND_OFFSET + num + 1; |
1347 /* We are no spectator and the player we want to give money to is no spectator and money gifts are allowed */ |
1356 w->SetDirty(); |
1348 if (IsValidPlayer(_network_playas) && IsValidPlayer(ci->client_playas) && _patches.give_money) { |
1357 return false; |
1349 GetString(this->action[i], STR_NETWORK_CLIENTLIST_GIVE_MONEY, lastof(this->action[i])); |
1358 } |
1350 this->proc[i++] = &ClientList_GiveMoney; |
1359 return true; |
1351 } |
1360 } |
1352 } |
1361 |
1353 |
1362 /** |
1354 /* A server can kick clients (but not himself) */ |
1363 * Finds the amount of actions in the popup and set the height correct |
1355 if (_network_server && _network_own_client_index != ci->client_index) { |
1364 */ |
1356 GetString(this->action[i], STR_NETWORK_CLIENTLIST_KICK, lastof(this->action[i])); |
1365 static uint ClientListPopupHeight() |
1357 this->proc[i++] = &ClientList_Kick; |
1366 { |
1358 |
1367 int num = 0; |
1359 sprintf(this->action[i],"Ban"); // XXX GetString? |
1368 |
1360 this->proc[i++] = &ClientList_Ban; |
1369 // Find the amount of actions |
1361 } |
1370 for (int i = 0; i < MAX_CLIENTLIST_ACTION; i++) { |
1362 |
1371 if (_clientlist_action[i][0] == '\0') continue; |
1363 if (i == 0) { |
1372 if (_clientlist_proc[i] == NULL) continue; |
1364 GetString(this->action[i], STR_NETWORK_CLIENTLIST_NONE, lastof(this->action[i])); |
1373 num++; |
1365 this->proc[i++] = &ClientList_None; |
1374 } |
1366 } |
1375 |
1367 |
1376 num *= CLNWND_ROWSIZE; |
1368 /* Calculate the height */ |
1377 |
1369 int h = ClientListPopupHeight(); |
1378 return num + 1; |
1370 |
1379 } |
1371 /* Allocate the popup */ |
|
1372 this->widget[0].bottom = this->widget[0].top + h; |
|
1373 this->widget[0].right = this->widget[0].left + 150; |
|
1374 |
|
1375 this->flags4 &= ~WF_WHITE_BORDER_MASK; |
|
1376 |
|
1377 this->FindWindowPlacementAndResize(150, h + 1); |
|
1378 } |
|
1379 |
|
1380 /** |
|
1381 * An action is clicked! What do we do? |
|
1382 */ |
|
1383 void HandleClientListPopupClick(byte index) |
|
1384 { |
|
1385 /* A click on the Popup of the ClientList.. handle the command */ |
|
1386 if (index < MAX_CLIENTLIST_ACTION && this->proc[index] != NULL) { |
|
1387 this->proc[index](this->client_no); |
|
1388 } |
|
1389 } |
|
1390 |
|
1391 /** |
|
1392 * Finds the amount of actions in the popup and set the height correct |
|
1393 */ |
|
1394 uint ClientListPopupHeight() |
|
1395 { |
|
1396 int num = 0; |
|
1397 |
|
1398 // Find the amount of actions |
|
1399 for (int i = 0; i < MAX_CLIENTLIST_ACTION; i++) { |
|
1400 if (this->action[i][0] == '\0') continue; |
|
1401 if (this->proc[i] == NULL) continue; |
|
1402 num++; |
|
1403 } |
|
1404 |
|
1405 num *= CLNWND_ROWSIZE; |
|
1406 |
|
1407 return num + 1; |
|
1408 } |
|
1409 |
|
1410 |
|
1411 virtual void OnPaint() |
|
1412 { |
|
1413 DrawWindowWidgets(this); |
|
1414 |
|
1415 /* Draw the actions */ |
|
1416 int sel = this->sel_index; |
|
1417 int y = 1; |
|
1418 for (int i = 0; i < MAX_CLIENTLIST_ACTION; i++, y += CLNWND_ROWSIZE) { |
|
1419 if (this->action[i][0] == '\0') continue; |
|
1420 if (this->proc[i] == NULL) continue; |
|
1421 |
|
1422 TextColour colour; |
|
1423 if (sel-- == 0) { // Selected item, highlight it |
|
1424 GfxFillRect(1, y, 150 - 2, y + CLNWND_ROWSIZE - 1, 0); |
|
1425 colour = TC_WHITE; |
|
1426 } else { |
|
1427 colour = TC_BLACK; |
|
1428 } |
|
1429 |
|
1430 DoDrawString(this->action[i], 4, y, colour); |
|
1431 } |
|
1432 } |
|
1433 |
|
1434 virtual void OnMouseLoop() |
|
1435 { |
|
1436 /* We selected an action */ |
|
1437 int index = (_cursor.pos.y - this->top) / CLNWND_ROWSIZE; |
|
1438 |
|
1439 if (_left_button_down) { |
|
1440 if (index == -1 || index == this->sel_index) return; |
|
1441 |
|
1442 this->sel_index = index; |
|
1443 this->SetDirty(); |
|
1444 } else { |
|
1445 if (index >= 0 && _cursor.pos.y >= this->top) { |
|
1446 HandleClientListPopupClick(index); |
|
1447 } |
|
1448 |
|
1449 DeleteWindowById(WC_TOOLBAR_MENU, 0); |
|
1450 } |
|
1451 } |
|
1452 }; |
1380 |
1453 |
1381 /** |
1454 /** |
1382 * Show the popup (action list) |
1455 * Show the popup (action list) |
1383 */ |
1456 */ |
1384 static Window *PopupClientList(Window *w, int client_no, int x, int y) |
1457 static void PopupClientList(int client_no, int x, int y) |
1385 { |
1458 { |
1386 int i; |
|
1387 const NetworkClientInfo *ci; |
|
1388 DeleteWindowById(WC_TOOLBAR_MENU, 0); |
1459 DeleteWindowById(WC_TOOLBAR_MENU, 0); |
1389 |
1460 |
1390 /* Clean the current actions */ |
1461 if (NetworkFindClientInfo(client_no) == NULL) return; |
1391 for (i = 0; i < MAX_CLIENTLIST_ACTION; i++) { |
1462 |
1392 _clientlist_action[i][0] = '\0'; |
1463 new NetworkClientListPopupWindow(x, y, _client_list_popup_widgets, client_no); |
1393 _clientlist_proc[i] = NULL; |
|
1394 } |
|
1395 |
|
1396 /* |
|
1397 * Fill the actions this client has. |
|
1398 * Watch is, max 50 chars long! |
|
1399 */ |
|
1400 |
|
1401 ci = NetworkFindClientInfo(client_no); |
|
1402 if (ci == NULL) return NULL; |
|
1403 |
|
1404 i = 0; |
|
1405 if (_network_own_client_index != ci->client_index) { |
|
1406 GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT, lastof(_clientlist_action[i])); |
|
1407 _clientlist_proc[i++] = &ClientList_SpeakToClient; |
|
1408 } |
|
1409 |
|
1410 if (IsValidPlayer(ci->client_playas) || ci->client_playas == PLAYER_SPECTATOR) { |
|
1411 GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY, lastof(_clientlist_action[i])); |
|
1412 _clientlist_proc[i++] = &ClientList_SpeakToCompany; |
|
1413 } |
|
1414 GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL, lastof(_clientlist_action[i])); |
|
1415 _clientlist_proc[i++] = &ClientList_SpeakToAll; |
|
1416 |
|
1417 if (_network_own_client_index != ci->client_index) { |
|
1418 /* We are no spectator and the player we want to give money to is no spectator and money gifts are allowed */ |
|
1419 if (IsValidPlayer(_network_playas) && IsValidPlayer(ci->client_playas) && _patches.give_money) { |
|
1420 GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_GIVE_MONEY, lastof(_clientlist_action[i])); |
|
1421 _clientlist_proc[i++] = &ClientList_GiveMoney; |
|
1422 } |
|
1423 } |
|
1424 |
|
1425 /* A server can kick clients (but not himself) */ |
|
1426 if (_network_server && _network_own_client_index != ci->client_index) { |
|
1427 GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_KICK, lastof(_clientlist_action[i])); |
|
1428 _clientlist_proc[i++] = &ClientList_Kick; |
|
1429 |
|
1430 sprintf(_clientlist_action[i],"Ban"); // XXX GetString? |
|
1431 _clientlist_proc[i++] = &ClientList_Ban; |
|
1432 } |
|
1433 |
|
1434 if (i == 0) { |
|
1435 GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_NONE, lastof(_clientlist_action[i])); |
|
1436 _clientlist_proc[i++] = &ClientList_None; |
|
1437 } |
|
1438 |
|
1439 /* Calculate the height */ |
|
1440 int h = ClientListPopupHeight(); |
|
1441 |
|
1442 /* Allocate the popup */ |
|
1443 w = new Window(x, y, 150, h + 1, ClientListPopupWndProc, WC_TOOLBAR_MENU, _client_list_popup_widgets); |
|
1444 w->widget[0].bottom = w->widget[0].top + h; |
|
1445 w->widget[0].right = w->widget[0].left + 150; |
|
1446 |
|
1447 w->flags4 &= ~WF_WHITE_BORDER_MASK; |
|
1448 WP(w, menu_d).item_count = 0; |
|
1449 // Save our client |
|
1450 WP(w, menu_d).main_button = client_no; |
|
1451 WP(w, menu_d).sel_index = 0; |
|
1452 |
|
1453 return w; |
|
1454 } |
|
1455 |
|
1456 /** Main handle for the client popup list |
|
1457 * uses menu_d WP macro */ |
|
1458 static void ClientListPopupWndProc(Window *w, WindowEvent *e) |
|
1459 { |
|
1460 switch (e->event) { |
|
1461 case WE_PAINT: { |
|
1462 DrawWindowWidgets(w); |
|
1463 |
|
1464 /* Draw the actions */ |
|
1465 int sel = WP(w, menu_d).sel_index; |
|
1466 int y = 1; |
|
1467 for (int i = 0; i < MAX_CLIENTLIST_ACTION; i++, y += CLNWND_ROWSIZE) { |
|
1468 if (_clientlist_action[i][0] == '\0') continue; |
|
1469 if (_clientlist_proc[i] == NULL) continue; |
|
1470 |
|
1471 TextColour colour; |
|
1472 if (sel-- == 0) { // Selected item, highlight it |
|
1473 GfxFillRect(1, y, 150 - 2, y + CLNWND_ROWSIZE - 1, 0); |
|
1474 colour = TC_WHITE; |
|
1475 } else { |
|
1476 colour = TC_BLACK; |
|
1477 } |
|
1478 |
|
1479 DoDrawString(_clientlist_action[i], 4, y, colour); |
|
1480 } |
|
1481 } break; |
|
1482 |
|
1483 case WE_MOUSELOOP: { |
|
1484 /* We selected an action */ |
|
1485 int index = (_cursor.pos.y - w->top) / CLNWND_ROWSIZE; |
|
1486 |
|
1487 if (_left_button_down) { |
|
1488 if (index == -1 || index == WP(w, menu_d).sel_index) return; |
|
1489 |
|
1490 WP(w, menu_d).sel_index = index; |
|
1491 w->SetDirty(); |
|
1492 } else { |
|
1493 if (index >= 0 && _cursor.pos.y >= w->top) { |
|
1494 HandleClientListPopupClick(index, WP(w, menu_d).main_button); |
|
1495 } |
|
1496 |
|
1497 DeleteWindowById(WC_TOOLBAR_MENU, 0); |
|
1498 } |
|
1499 } break; |
|
1500 } |
|
1501 } |
1464 } |
1502 |
1465 |
1503 /** |
1466 /** |
1504 * Main handle for clientlist |
1467 * Main handle for clientlist |
1505 */ |
1468 */ |
1506 static void ClientListWndProc(Window *w, WindowEvent *e) |
1469 struct NetworkClientListWindow : Window |
1507 { |
1470 { |
1508 switch (e->event) { |
1471 byte selected_item; |
1509 case WE_PAINT: { |
1472 byte selected_y; |
1510 NetworkClientInfo *ci; |
1473 |
1511 int i = 0; |
1474 NetworkClientListWindow(const WindowDesc *desc, WindowNumber window_number) : |
1512 |
1475 Window(desc, window_number), |
1513 /* Check if we need to reset the height */ |
1476 selected_item(0), |
1514 if (!CheckClientListHeight(w)) break; |
1477 selected_y(255) |
1515 |
1478 { |
1516 DrawWindowWidgets(w); |
1479 this->FindWindowPlacementAndResize(desc); |
1517 |
1480 } |
1518 int y = CLNWND_OFFSET; |
1481 |
1519 |
1482 /** |
1520 FOR_ALL_ACTIVE_CLIENT_INFOS(ci) { |
1483 * Finds the amount of clients and set the height correct |
1521 TextColour colour; |
1484 */ |
1522 if (_selected_clientlist_item == i++) { // Selected item, highlight it |
1485 bool CheckClientListHeight() |
1523 GfxFillRect(1, y, 248, y + CLNWND_ROWSIZE - 1, 0); |
1486 { |
1524 colour = TC_WHITE; |
1487 int num = 0; |
1525 } else { |
1488 const NetworkClientInfo *ci; |
1526 colour = TC_BLACK; |
1489 |
1527 } |
1490 /* Should be replaced with a loop through all clients */ |
1528 |
1491 FOR_ALL_ACTIVE_CLIENT_INFOS(ci) { |
1529 if (ci->client_index == NETWORK_SERVER_INDEX) { |
1492 num++; |
1530 DrawString(4, y, STR_NETWORK_SERVER, colour); |
1493 } |
1531 } else { |
1494 |
1532 DrawString(4, y, STR_NETWORK_CLIENT, colour); |
1495 num *= CLNWND_ROWSIZE; |
1533 } |
1496 |
1534 |
1497 /* If height is changed */ |
1535 /* Filter out spectators */ |
1498 if (this->height != CLNWND_OFFSET + num + 1) { |
1536 if (IsValidPlayer(ci->client_playas)) DrawPlayerIcon(ci->client_playas, 64, y + 1); |
1499 // XXX - magic unfortunately; (num + 2) has to be one bigger than heigh (num + 1) |
1537 |
1500 this->SetDirty(); |
1538 DoDrawString(ci->client_name, 81, y, colour); |
1501 this->widget[3].bottom = this->widget[3].top + num + 2; |
1539 |
1502 this->height = CLNWND_OFFSET + num + 1; |
1540 y += CLNWND_ROWSIZE; |
1503 this->SetDirty(); |
|
1504 return false; |
|
1505 } |
|
1506 return true; |
|
1507 } |
|
1508 |
|
1509 virtual void OnPaint() |
|
1510 { |
|
1511 NetworkClientInfo *ci; |
|
1512 int i = 0; |
|
1513 |
|
1514 /* Check if we need to reset the height */ |
|
1515 if (!this->CheckClientListHeight()) return; |
|
1516 |
|
1517 DrawWindowWidgets(this); |
|
1518 |
|
1519 int y = CLNWND_OFFSET; |
|
1520 |
|
1521 FOR_ALL_ACTIVE_CLIENT_INFOS(ci) { |
|
1522 TextColour colour; |
|
1523 if (this->selected_item == i++) { // Selected item, highlight it |
|
1524 GfxFillRect(1, y, 248, y + CLNWND_ROWSIZE - 1, 0); |
|
1525 colour = TC_WHITE; |
|
1526 } else { |
|
1527 colour = TC_BLACK; |
1541 } |
1528 } |
1542 } break; |
1529 |
1543 |
1530 if (ci->client_index == NETWORK_SERVER_INDEX) { |
1544 case WE_CLICK: |
1531 DrawString(4, y, STR_NETWORK_SERVER, colour); |
1545 /* Show the popup with option */ |
1532 } else { |
1546 if (_selected_clientlist_item != 255) { |
1533 DrawString(4, y, STR_NETWORK_CLIENT, colour); |
1547 PopupClientList(w, _selected_clientlist_item, e->we.click.pt.x + w->left, e->we.click.pt.y + w->top); |
|
1548 } |
1534 } |
1549 break; |
1535 |
1550 |
1536 /* Filter out spectators */ |
1551 case WE_MOUSEOVER: |
1537 if (IsValidPlayer(ci->client_playas)) DrawPlayerIcon(ci->client_playas, 64, y + 1); |
1552 /* -1 means we left the current window */ |
1538 |
1553 if (e->we.mouseover.pt.y == -1) { |
1539 DoDrawString(ci->client_name, 81, y, colour); |
1554 _selected_clientlist_y = 0; |
1540 |
1555 _selected_clientlist_item = 255; |
1541 y += CLNWND_ROWSIZE; |
1556 w->SetDirty(); |
1542 } |
1557 break; |
1543 } |
1558 } |
1544 |
1559 /* It did not change.. no update! */ |
1545 virtual void OnClick(Point pt, int widget) |
1560 if (e->we.mouseover.pt.y == _selected_clientlist_y) break; |
1546 { |
1561 |
1547 /* Show the popup with option */ |
1562 /* Find the new selected item (if any) */ |
1548 if (this->selected_item != 255) { |
1563 _selected_clientlist_y = e->we.mouseover.pt.y; |
1549 PopupClientList(this->selected_item, pt.x + this->left, pt.y + this->top); |
1564 if (e->we.mouseover.pt.y > CLNWND_OFFSET) { |
1550 } |
1565 _selected_clientlist_item = (e->we.mouseover.pt.y - CLNWND_OFFSET) / CLNWND_ROWSIZE; |
1551 } |
1566 } else { |
1552 |
1567 _selected_clientlist_item = 255; |
1553 virtual void OnMouseOver(Point pt, int widget) |
1568 } |
1554 { |
1569 |
1555 /* -1 means we left the current window */ |
1570 /* Repaint */ |
1556 if (pt.y == -1) { |
1571 w->SetDirty(); |
1557 this->selected_y = 0; |
1572 break; |
1558 this->selected_item = 255; |
1573 |
1559 this->SetDirty(); |
1574 case WE_DESTROY: case WE_CREATE: |
1560 return; |
1575 /* When created or destroyed, data is reset */ |
1561 } |
1576 _selected_clientlist_item = 255; |
1562 /* It did not change.. no update! */ |
1577 _selected_clientlist_y = 0; |
1563 if (pt.y == this->selected_y) return; |
1578 break; |
1564 |
1579 } |
1565 /* Find the new selected item (if any) */ |
1580 } |
1566 this->selected_y = pt.y; |
|
1567 if (pt.y > CLNWND_OFFSET) { |
|
1568 this->selected_item = (pt.y - CLNWND_OFFSET) / CLNWND_ROWSIZE; |
|
1569 } else { |
|
1570 this->selected_item = 255; |
|
1571 } |
|
1572 |
|
1573 /* Repaint */ |
|
1574 this->SetDirty(); |
|
1575 } |
|
1576 }; |
1581 |
1577 |
1582 void ShowClientList() |
1578 void ShowClientList() |
1583 { |
1579 { |
1584 AllocateWindowDescFront<Window>(&_client_list_desc, 0); |
1580 AllocateWindowDescFront<NetworkClientListWindow>(&_client_list_desc, 0); |
1585 } |
1581 } |
1586 |
1582 |
1587 |
1583 |
1588 static NetworkPasswordType pw_type; |
1584 static NetworkPasswordType pw_type; |
1589 |
1585 |